Dot-Net

MVP 中使用 WinForms 進行非同步呼叫的最佳實踐

  • August 30, 2016

我在 WinForms 項目中使用 Model-View-Presenter 模式,我遇到的一個問題(在許多問題中)是當表單告訴展示者做某事,然後在展示者去做時沒有反應。幸運的是,在我的項目中,讓所有展示者呼叫非同步都沒有問題,問題是如何做到這一點?

是否應該將每個展示者呼叫都包含在一個新的執行緒創建中?*

new Thread(()=>_presenter.DoSomething()).Start();

這裡的最佳實踐是什麼?如果使用者按下“中止你正在做的事情”按鈕怎麼辦?如何優雅地中止?

.* 實際上,我可能只是在展示者上使用某種代理來執行此操作,而不是將執行緒創建放在 WinForm 中

我只能聲稱我已經考慮過這一點(在閱讀您的問題之前;)。首先,我會安裝這實際上很重要的地方;例如數據庫訪問阻塞點。如果在“UI”上下文中存在不應該執行的地方(您可以從http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.current.aspx在 UI 執行緒中保存它然後稍後與非 UI 同步上下文進行比較)然後 Debug.BitchAndMoan() 關於它。任何更長的計算(“應該”在它們自己的流形中都清楚地分開,對;)應該斷言。

我想你至少應該通過屬性配置展示者函式的執行類型,然後由代理遵守。(以防萬一您想以串列方式完成某些事情)。

取消任務實際上是展示者的問題,但您必須有一個參考對象,告訴您要停止什麼。如果您採用代理方式,那麼您可以使用 IAsyncResult 將創建的執行緒拾取到任務列表中,但是如果允許並行呼叫多次相同的操作,那麼決定取消哪個執行緒仍然是一個問題。因此,您必須在啟動任務時為任務提供合適的特定於呼叫的名稱;這意味著 View 方面的邏輯太多 - > Presenter 可能應該要求 View 詢問使用者應該處理哪一項任務。

我的經驗是,這通常只是通過使用事件(SCSF 風格)來解決。如果從頭開始做,我會選擇代理方式,因為 SCSF 在很多方面都很痛苦,以至於我懷疑它的設計師的理智。

我通常將任何可能(實際上)花費一兩秒以上的操作放入單獨的任務中,例如:

public interface ITask
{
   void ExecuteTask (ITaskExecutionContext context);
   void AfterSuccess(ITaskExecutionContext context);
   void AfterFailure(ITaskExecutionContext context);
   void AfterAbortion(ITaskExecutionContext context);
}

我還有一個用於執行此類任務的抽象:

public interface ITaskExecutor : IDisposable
{
   void BeginTask(ITask task);
   void TellTaskToStop();
}

其中一種實現ITaskExecutor是使用BackgroundWorker

public class BackgroundTaskExecutor : ITaskExecutor
{
   public void BeginTask(ITask task)
   {
       this.task = task;
       worker = new BackgroundWorker ();
       worker.DoWork += WorkerDoWork;
       worker.RunWorkerCompleted += WorkerRunWorkerCompleted;
       worker.WorkerSupportsCancellation = true;

       worker.RunWorkerAsync();
   }

   ...
}

我嚴重依賴依賴注入和 IoC 將事物連接在一起。在展示者中,我只是呼叫如下內容:

GoAndDontReturnUntilYouBringMeALotOfMoneyTask task = new GoAndDontReturnUntilYouBringMeALotOfMoneyTask(parameters);
taskExecutor.BeginTask(task);

然後連接取消/中止按鈕,以便它們告訴任務執行器/任務中止。

它實際上比這裡介紹的要復雜一些,但這是一般的想法。

引用自:https://stackoverflow.com/questions/831051