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将自动在另一个线程上运行,因为它们是长时间运行的任务。
希望有人能帮助
问候,
这个问题有两种可能的方法。最优雅的可能也是"最佳实践"(如果我错了,请随时纠正我(是使处理程序方法本身异步无效。需要说明的是:这是唯一应该使用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);
}