【发布时间】:2014-03-18 18:15:21
【问题描述】:
我正在尝试在多线程环境中更新进度条。我知道很多问题已经解决了这个问题,但没有一个提议的解决方案对我有用。 这是我的代码的主干:
public static void DO_Computation(//parameters) {
//Intialisation of parameters
Parallel.For(struct initialisation with local data) {
//business logic
//Call to update_progressbar (located in an another class, as the DO_Computation function is in Computation.cs class (not deriving from Form).
WinForm.Invoke((Action)delegate {Update_Progress_Bar(i);}); //WinForm is a class that exposes the progressbar.
}
}
这个不行(进度条到100%就卡住了,这是正常的(这件事我们可以参考microsoft article(确实,这不是线程安全的操作方式))。
Microsoft 站点规定将Parallel.For 循环包装到Task 例程中,如下所示:
public static void DO_Computation(//parameters) {
//Intialisation of parameters
Task.Factory.StartNew(() =>
{
Parallel.For(struct initialosation with local data) {
//business logic
//Call to update_progressbar (ocated in an another class, as the DO_Computation function is in Computation.cs class (not deriving from Form).
WinForm.Invoke((Action)delegate {Update_Progress_Bar(i);}); //WinForm is a class that exposes the progressbar.
..
}
});
});
但是这并不好用,当调试线程时直接超出了任务范围。
编辑 2:
基本上,我的问题分为 3 个部分:Computation.cs(DO_Computation 被暴露),WinForm 是包含进度条的表单,MainWindow 是包含按钮的表单单击时打开带有进度条的表单。
我不清楚在这种情况下“任务”的用途是什么。
因为它超出了任务范围而没有执行任何Parallel.For 工作
有什么想法吗?
非常感谢,
编辑 3:
我在 Noseratio 的帮助下升级了我的代码(这对他来说意义重大)。但是我有同样的问题,即任务中的代码永远不会执行。我的代码现在看起来像:
DoComputation method
//Some Initilasations here
Action enableUI = () =>
{
frmWinProg.SetProgressText("Grading Transaction...");
frmWinProg.ChangeVisibleIteration(true);
};
Action<Exception> handleError = (ex) =>
{
// error reporting
MessageBox.Show(ex.Message);
};
var cts = new CancellationTokenSource();
var token = cts.Token;
Action cancel_work = () =>
{
frmWinProg.CancelTransaction();
cts.Cancel();
};
var syncConext = SynchronizationContext.Current;
Action<int> progressReport = (i) =>
syncConext.Post(_ => frmWinProg.SetIteration(i,GrpModel2F.NumOfSim, true), null);
var task = Task.Factory.StartNew(() =>
{
ParallelLoopResult res = Parallel.For<LocalDataStruct>(1,NbSim, options,
() => new DataStruct(//Hold LocalData for each thread),
(iSim, loopState, DataStruct) =>
//Business Logic
if (token.IsCancellationRequested)
{
loopState.Stop();
}
progressReport(iSim);
//Business Logic
return DataStruct;
},
(DataStruct) =>
//Assiginig Results;
});//Parallel.For end
}, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
task.ContinueWith(_ =>
{
try
{
task.Wait();
}
catch (Exception ex)
{
while (ex is AggregateException && ex.InnerException != null)
ex = ex.InnerException;
handleError(ex);
}
enableUI();
}, TaskScheduler.FromCurrentSynchronizationContext
());
请注意,Do_Computation 函数本身是从在其上运行 BackGroundWorker 的表单调用的。
【问题讨论】:
-
请格式化代码,使其真正可读。
-
发现问题出在哪里(代码上部的委托使整个事情在另一个线程上工作。因此,调用在另一个线程上创建的
frmWinProg最终导致了僵局。感谢您的帮助,非常感谢
标签: c# .net multithreading task-parallel-library async-await