【发布时间】:2011-12-22 20:14:48
【问题描述】:
我正在使用后台工作人员来完成我的所有处理。在那里,我有很多地方可以写入“日志”文本框。所有这些工作都很好,但在后台工作人员的最后,最后一行,我通过SynchronizationContext 再打了一个电话,但没有触发。为什么所有其他调用都有效,而不是最后一个?
我应该补充一点,应用程序只是“挂起”,甚至还有一个 EventLog 条目说:
程序 MVST.CodeSync.exe 版本 2.0.0.0 停止与 Windows 交互并被关闭。 要查看有关问题的更多信息是否可用,请查看操作中心控制面板中的问题历史记录。 进程 ID:1f5c 开始时间:01ccc0e2e7ca1d42 终止时间:16 应用程序路径:C:\Users\ganders\Desktop\NewCodeSync\MVST.CodeSync.exe 报告 ID:629f3533-2cd6-11e1-9e15-005056b75254这里是DoWork方法(调用RunWorkerAsync时执行):
private void bgw_StartCompare(object sender, DoWorkEventArgs e)
{
OnWriteLogArgs args = null;
CompareData compareData = e.Argument as CompareData;
// We need to iterate through all of the nodes and if they are checked, continue
foreach (TreeNode subSystemNode in compareData.TreeNodes)
{
if (!subSystemNode.Checked)
continue;
args = new OnWriteLogArgs(String.Format("-------------------------- Comparing sub-system: \"{0}\" with CompareType: \"{1}\" --------------------------", subSystemNode.Text, compareData.CompareType));
syncContext.Post(delegate { OnWriteLog(args); }, null);
// Each of these nodes should be a server, so continue
foreach (TreeNode serverNode in subSystemNode.Nodes)
{
if (!serverNode.Checked)
continue;
args = new OnWriteLogArgs(String.Format("-------------------------- Comparing server: \"{0}\" with CompareType: \"{1}\" --------------------------", serverNode.Text, compareData.CompareType));
syncContext.Post(delegate { OnWriteLog(args); }, null);
// The "tag" contains the server information that we need to do the comparison
CustomConfig.Server server = (CustomConfig.Server)serverNode.Tag;
if (!compareData.DoneInitialCompare)
CompareAll(compareData, server, string.Empty, server.CompareBasePath, serverNode, compareData.CompareType);
else
CompareAllByTreeNode(compareData, server, serverNode, compareData.CompareType);
}
}
syncContext.Post(delegate { OnWriteLog(new OnWriteLogArgs("Finished the compare...")); }, null);
RebuildTreeViewArgs rArgs = new RebuildTreeViewArgs(compareData.OnlyShowDifferences, compareData.TreeNodes);
syncContext.Post(delegate { OnRebuildTreeView(rArgs); }, null);
MessageBox.Show("It made it...");
syncContext.Post(delegate { OnWriteLog(new OnWriteLogArgs("Finished calling the rebuild tree view method...")); }, null);
}
您会注意到在foreach 循环结束时,我写了Finished the compare...,并且确实写了,但是下一个同步调用:
syncContext.Post(delegate { OnRebuildTreeView(rArgs); }, null);
永远不会被处决。方法如下:
private void OnRebuildTreeView(RebuildTreeViewArgs args)
{
syncContext.Post(delegate { OnWriteLog(new OnWriteLogArgs("Made it to the OnRebuildTreeView method...")); }, null);
while (bgw.IsBusy)
{
syncContext.Post(delegate { OnWriteLog(new OnWriteLogArgs("Sleeping...")); }, null);
Thread.Sleep(1000);
}
syncContext.Post(delegate { OnWriteLog(new OnWriteLogArgs("Starting the rebuild of the TreeView...")); }, null);
TreeNode[] tn = args.NewStructure;
tvSync.Nodes.Clear();
foreach (TreeNode node in tn)
tvSync.Nodes.Add(node);
foreach (TreeNode node in tvSync.Nodes)
FixCheckedAndUnCheckedNodes(node);
ReloadTreeView(args.OnlyShowDifferences);
}
【问题讨论】:
-
如果
OnRebuildTreeView已经在 GUI 线程中运行,为什么还要继续调用syncContext完全有想法.. 我不知道这些是否使您的应用程序挂起,但它们看起来不太好。.Post也不会阻止调用者,如果您的逻辑需要阻止使用.Send而不是 -
好点子,没想到从 OnRebuildTreeView 方法调用 syncContext ......我会拿出来的。至于 Thread.Sleep(),我只是添加了以防万一……(更多调试尝试)。我会删除那些东西,然后再试一次。谢谢
-
如果您将
OnRebuildTreeView附加到RunWorkerCompleted事件可能会使事情变得更简单,从您的代码看来,您似乎只想在线程的主要方法完成后执行它。 -
我猜你的
syncContext指的是 UI 线程。我认为您应该改用ReportProgress()方法和ProgressChanged事件。您是否尝试过在调试模式下逐步执行该方法?然后你会看到哪个方法挂了。 -
Matthias,我没有这样做,因为在 CompareAll() 和 CompareByTreeNode() 方法(从上面显示的 DoWork() 方法中调用)中,每个人都启动了线程正在比较的文件。所以 backgroundworker 正在运行,目录中的每个文件都有 1 个线程。我认为这会引起混乱,但也许不会。我花了大约 10 个小时将这个实用程序重新编写为多线程,不确定我是多么渴望回去“尝试”该配置。
标签: c# multithreading synchronization backgroundworker synchronizationcontext