MVP处理长期任务

本文关键字:任务 处理 MVP | 更新日期: 2023-09-27 18:15:17

我正在编写使用.net C#在Winform上应用MVP(Model,View,Presenter(的软件。我在设计处理长期任务(需要时间进行计算和响应(的Presenter类时遇到了麻烦。我在互联网上研究过,知道如何在.net 4.5上使用TPL Task或async/await。但在这样做的过程中,我需要将其应用于每个行动。

现在,我想设计Presenter类,它从视图中接收操作,在其他线程中自动执行这些操作(如使用Task、ThreadPool…(,并在没有任何跨线程异常的情况下将结果更新回GUI。

示例:我想控制Robot,我有RobotView、RobotPresenter和RobotController来处理发送到Rotbot devive的所有操作在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

在演示者处:我调用RobotController(Model(执行需要很长时间的Home操作(向设备发送命令,等待返回响应(

  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

所以,它起了作用,但我需要应用Task。运行/GetAwaiter。。。所有动作(ArmUp,ArmDown,Extend,Retract,…(。我也为其他演示者(其他设备(做同样的事情。这是非常浪费时间的。

我想设计一种方式,让视图中的每个函数都调用Presenter。DoSomeThing将自动在另一个线程上运行,因为它们是长时间运行的任务。

希望有人能帮助

问候,

MVP处理长期任务

这个问题有两种可能的方法。最优雅的可能也是"最佳实践"(如果我错了,请随时纠正我(是使处理程序方法本身异步无效。需要说明的是:这是唯一应该使用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);
}