C# 任务继续以保持UI线程响应能力
我正在使用WinForms中的任务从UI线程中删除昂贵的方法。在我的updateComplete和updateFailed任务中,我必须将_UpdateMessageAskinProgress设置为false并启用我的控件。有什么方法可以在一个单独的任务中做到这一点,其中updateComplete或updateFailed在完成后继续执行(因为我目前有重复的代码)?另外,有没有更好的方法来实现_updateMessageAskinProgress?我不希望同时运行多个任务C# 任务继续以保持UI线程响应能力,c#,task-parallel-library,C#,Task Parallel Library,我正在使用WinForms中的任务从UI线程中删除昂贵的方法。在我的updateComplete和updateFailed任务中,我必须将_UpdateMessageAskinProgress设置为false并启用我的控件。有什么方法可以在一个单独的任务中做到这一点,其中updateComplete或updateFailed在完成后继续执行(因为我目前有重复的代码)?另外,有没有更好的方法来实现_updateMessageAskinProgress?我不希望同时运行多个任务 private vo
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());
}
}
我会用这个。下面是我使用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);
}
}
你为什么不提取一个方法呢
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());
}
}
您必须访问任务。失败的处理程序中存在异常,以避免任务终结时出现异常您的
\u updateMessageAskinProgress
具有竞争条件:如果两个任务几乎同时启动,则两个任务可能同时运行。问了这么多问题:这是一个怎样的EAP?(我在代码中没有看到任何事件。)将asyncTask
作为从未使用过的参数有什么意义?为什么asynchmethod
将TaskScheduler
作为参数?它是EAP-这里是任务。ContinueWith
是我们的事件。延续执行通常由AsyncCallback委托执行的工作。当antecedent完成并且数据缓冲区已填充时,将调用它<使用code>asyncTask,它被传递到方法中以供我使用(我在问题中声明,这是我所拥有的一些代码的一个修剪版本-也许我应该再修剪一下:)。最后,将uiScheduler
传递到方法中,以便在该方法中可以更新UI线程。这实际上不是EAP。EAP实际上使用事件,例如ContinueWith
不是事件,这是一种传递委托的方法。我提供的指向MSDN的链接建议使用相反的方法。。。EAP本质上是为多线程实现提供大量工具的任何东西(不是吗?)。尽管对于第三方物流来说,这可能需要很多伪装,但我认为这是基于文档中所述的伪装之一。你的观点被采纳了……如果你阅读了你链接的文档中的第二个项目符号,它准确地描述了EAP的样子:一个方法和一个完成的事件。其他任何东西都不是EAP。
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());
}
}