2016-10-27 3 views
0

MVP (Model, View, Presenter)를 Winform에 적용한 소프트웨어를 .NET C#을 사용하여 작성했습니다. 장기 실행 작업 (계산 및 응답 시간 소요)을 처리하는 Presenter 클래스를 설계하는 데 어려움이 있습니다. 인터넷에서 연구했고 .net 4.5에서 TPL Task 또는 async/await를 사용하는 방법을 알고 있습니다. 그러나 그렇게함으로써 각 행동에 대해 적용해야합니다.MVP (long run task) 처리

이제보기에서 동작을 수신하는 Presenter 클래스를 설계하고 다른 스레드 (예 : TaskPool, ThreadPool 등)에서 자동으로 실행하고 크로스 스레드 예외없이 GUI로 결과를 다시 업데이트하려고합니다.

예 : RobotView에 보낼 모든 작업을 처리하는 RobotView, RobotPresenter 및 RobotController가 있습니다. RobotView 클래스에서 HomeRobot 작업을 처리하고 발표자에게 전화를 겁니다.

Private Sub btnHome_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnHome.Click 
     AVPLib.Log.guiLogger.Info("Enter btnHome_Click") 
     Dim strMessageText As String = String.Empty 
     Try 
      strMessageText = AVPLib.ContainerData.GetMessageText("HomeButtonCenterRobotCassettes") 
      If Utils.ShowAVPMessageBox(strMessageText, HOME_TM, MessageBoxIcon.Question) = DialogResult.OK Then 
       **_presenter.HomeRobot()** 
       AVPLib.ContainerData.LogAlarmEvent(AVPLib.ContainerData.TypeUser, AVPLib.ContainerData.LogSource.AVPMainScreen, 
                  "[Main Screen]" & " Home Click") 
      End If 
     Catch ex As Exception 
      AVPLib.Log.avpLogger.Error(ex.ToString()) 
     End Try 
     AVPLib.Log.guiLogger.Info("Leave btnHome_Click") 
    End Sub 

은 발표자에 : 나는

Public Function HomeRobot() As Boolean 
     Dim result As Boolean = False 
     HEventLoggerWrapper.Debug("Enter HomeRobot.") 

     Try 
      _robotView.EnableDisableAllButton(False) 
      Dim taskResult As Task(Of Boolean) = Task.Run(Function() _robotController.SafetyHomeRobot()) 
      taskResult.GetAwaiter().OnCompleted(Sub() result = taskResult.Result) 

     Catch ex As Exception 
      LogParameterUtility.LogErrorParameter(HEventLoggerWrapper.Logger, 
                [GetType]().Name, 
                "HomeRobot", 
                MethodBase.GetCurrentMethod(), ex) 
     End Try 

     HEventLoggerWrapper.Debug("Leave HomeRobot. Result = " & result) 
     Return result 
    End Function 

그래서, 그것은 일 (장치에 명령을 보내 반환 응답을 기다리는) RobotController (모델) 시간이 오래 걸릴 홈 조치를 실행하기 위해 전화를하지만 필요 (ArmUp, ArmDown, Extend, Retract, ...) 모든 작업에 대해 Task.Run/GetAwaiter ...를 적용하십시오. 다른 발표자 (다른 장치)에게도 동일한 작업을 수행합니다. 그것은 매우 낭비입니다.

뷰 호출 Presenter.DoSomeThing의 모든 함수가 장기 실행 태스크이기 때문에 다른 스레드에서 자동으로 실행되는 방식을 설계하고 싶습니다.

희망 누군가가이 문제에 대한 두 가지 접근 방법이있다

+0

왜 지금까지 시도한 코드를 표시하지 않으시겠습니까? 당신을 도우려는 것이 훨씬 쉬울 것입니다. – SharpShade

+1

구체적인 문제는 무엇입니까? 당신이 말하는 것은 정확하지만 효과가없는 것은 무엇입니까? 지금까지의 나의 가정 : 당신은 TPL과 비동기/대기를 어떻게 사용하는지 실제로 알지 못했습니다. 힌트 : Presenter 메소드는'... async Task DoActionX()'로 선언되어야하며, Model 메소드는 * async *'Task' 또는'Task '으로 선언되어야합니다. 상황에 따라'await Model.DoActionX(). ConfigureAwait (...)'를 사용해야 할 수도 있습니다 (이 기사 [https://msdn.microsoft.com/en-us/magazine/jj991977.aspx] 참조).) 자세한 내용은). – SharpShade

+0

명확한 의미로 코드를 업데이트했습니다. – user2927954

답변

0

감사를 도울 수 있습니다. 가장 우아하고 아마도 "우수 사례"(내가 틀렸다면 나에게 맞춰주십시오)는 핸들러 메서드 자체를 비동기 무효으로 만드는 것입니다. 여기있다 : 이것은 경우에만 async void을 사용해야합니다. 그 외의 경우 항상 async Task을 사용하십시오!

처리기를 비동기로 설정하지 않으려면 Task.Factory.StartNew(PresenterActionMethod).ContinueWith(AnotherHandler);을 사용할 수도 있지만 이는 상대적으로 나쁜 방법입니다. UI 컨트롤을 변경하면 다른 스레드에서 호출되어 UI 스레드에서 호출해야하는 다른 핸들러 메소드가 필요합니다. Task.Wait(...)을 사용하면 UI 스레드를 차단하므로 제대로 작동하지 않습니다.

작은 부수 정보. 하지만 이렇게 사용하면 완벽하게 작동합니다.

///================================================================================================= 
/// <summary> Handler in your View class. </summary> 
/// 
/// <param name="sender"> Source of the event. </param> 
/// <param name="e">  Event information. </param> 
///================================================================================================= 
public async void ViewEventHandler(object sender, EventArgs e) 
{ 
    // Set some UI stuff 
    // Here we need to use ConfigureAwait(true) since we will interact with the UI after this method call 
    await PresenterActionMethod().ConfigureAwait(true); 

    // Set some UI stuff again 
} 

///================================================================================================= 
/// <summary> 
///  This method is inside your Presenter class and is expected to return once the long 
///  running method of your Model is finished. 
/// </summary> 
/// 
/// <returns> A Task. </returns> 
///================================================================================================= 
public async Task PresenterActionMethod() 
{ 
    // Do stuff 
    await ModelLongRunningTaskMethod().ConfigureAwait(false); 
    // Do other stuff 
} 

///================================================================================================= 
/// <summary> 
///  This method is inside your Model class and is expected to be a long-running method. 
/// </summary> 
/// 
/// <returns> A Task. </returns> 
///================================================================================================= 
public async Task ModelLongRunningTaskMethod() 
{ 
    // ... do your stuff here 
    // You should use ConfigureAwait(false) here since you don't need the captured context 
    // this improves performance and reduces the risk of deadlocks 
    await Task.Delay(6000).ConfigureAwait(false); 
}