我正在使用WinForms中的Tasks从我的UI线程中删除昂贵的方法。在我的updateComplete和updateFailed任务中,我必须将_updateMessageTaskInProgress设置为false并启用我的控件。有没有办法我可以在一个单独的任务中执行此操作,一旦完成(因为我目前有重复的代码),updateComplete或updateFailed也会继续执行?另外,有没有更好的方法来实现_updateMessageTaskInProgress - 我不希望同时运行多个任务。
private void PerformUpdate()
{
if (!_updateMessageTaskInProgress)
{
LoadButton.Enabled = false;
MonthEndDateEdit.Enabled = false;
BankIssuerListEdit.Enabled = false;
Task updateMessages = Task.Factory.StartNew(() =>
{
_updateMessageTaskInProgress = true;
ExpensiveMethod();
});
// Task runs when updateMessages completes without exception. Runs on UI thread.
Task updateComplete = updateMessages.ContinueWith(update =>
{
DoSuccessfulStuff();
_updateMessageTaskInProgress = false;
LoadButton.Enabled = true;
MonthEndDateEdit.Enabled = true;
BankIssuerListEdit.Enabled = true;
}, System.Threading.CancellationToken.None, TaskContinuationOptions.NotOnFaulted, TaskScheduler.FromCurrentSynchronizationContext());
// Task runs when updateMessages completes with exception. Runs on UI thread.
Task updateFailed = updateMessages.ContinueWith(task =>
{
DoFailureStuff();
_updateMessageTaskInProgress = false;
LoadButton.Enabled = true;
MonthEndDateEdit.Enabled = true;
BankIssuerListEdit.Enabled = true;
}, System.Threading.CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.FromCurrentSynchronizationContext());
}
}
答案 0 :(得分:2)
为什么不提取方法?
private void SetLock(bool lock)
{
LoadButton.Enabled = !lock;
MonthEndDateEdit.Enabled = !lock;
BankIssuerListEdit.Enabled = !lock;
_updateMessageTaskInProgress = lock;
}
private void PerformUpdate()
{
if (!_updateMessageTaskInProgress)
{
SetLock(true);
Task updateMessages = Task.Factory.StartNew(() =>
{
ExpensiveMethod();
});
// Task runs when updateMessages completes without exception. Runs on UI thread.
Task updateComplete = updateMessages.ContinueWith(update =>
{
DoSuccessfulStuff();
SetLock(false);
}, System.Threading.CancellationToken.None, TaskContinuationOptions.NotOnFaulted, TaskScheduler.FromCurrentSynchronizationContext());
// Task runs when updateMessages completes with exception. Runs on UI thread.
Task updateFailed = updateMessages.ContinueWith(task =>
{
DoFailureStuff();
SetLock(false);
}, System.Threading.CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.FromCurrentSynchronizationContext());
}
}
答案 1 :(得分:1)
我会使用Event Based Asynchronous-TYPE Pattern来做这件事。我用于使用TPL将方法分拆到后台线程的代码的简化版本在
下面private void TaskSpin(TaskScheduler uiScheduler,
Func<TaskScheduler, object[], bool> asyncMethod,
object[] methodParameters)
{
try
{
Task asyncTask = Task.Factory.StartNew<bool>(() =>
asyncMethod(uiScheduler, methodParameters));
// Callback for finish/cancellation.
asyncTask.ContinueWith(task =>
{
// Check task status.
switch (task.Status)
{
// Handle any exceptions to prevent UnobservedTaskException.
case TaskStatus.RanToCompletion:
if (asyncTask.Result)
UpdateUI(uiScheduler, "OK");
else
{
string strErrComplete = "Process failed.";
UpdateUI(uiScheduler, strErrComplete);
}
break;
case TaskStatus.Faulted:
string strFatalErr = String.Empty;
UpdateUI(uiScheduler, "Fatal Error);
if (task.Exception != null)
strFatalErr = task.Exception.InnerException.Message;
else
strFatalErr = "Operation failed";
MessageBox.Show(strFatalErr);
break;
}
asyncTask.Dispose();
return;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
catch (Exception eX)
{
Utils.ErrMsg(eX.Message);
}
}
我希望这会有所帮助。
编辑。注意,上面的uiScheduler
是UI线程的TaskScheduler
。那是
TaskSheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();