0

我有一个 [STAThread] main,其中包含以下内容:

try
{
    // Start the port enumerator.

    Enumerator enumerator = new Enumerator();

    // Display the main window and start everything going.

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new TopViewForm(ref enumerator));
}
catch (Exception)
{
}

枚举器对象本身包含一个后台工作线程。后台工作初始化如下:

MyBackgroundWorker = new BackgroundWorker();
MyBackgroundWorker.WorkerSupportsCancellation = true;
MyBackgroundWorker.WorkerReportsProgress = true;
MyBackgroundWorker.DoWork +=new DoWorkEventHandler(MyBackgroundWorker_DoWork);
MyBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(MyBackgroundWorker_ProgressChanged);
MyBackgroundWorker.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(MyBackgroundWorker_RunWorkerCompleted);
MyBackgroundWorker.RunWorkerAsync();

现在,为了向主窗体(TopViewForm 的实例)报告进度,Enumerator 中的线程正在使用一些适当的用户对象调用 ReportProgress。我假设 ReportProgress 将以 ProgressChanged 事件的形式到达并在主 UI 线程上执行,主 UI 线程是 Enumerator 本身创建的线程(即不是 BackgroundWorker 的线程)。

鉴于这种情况,当我尝试在主进程线程上的 TreeView 中设置一个节点以响应来自该对象的事件时,我怎么可能遇到跨线程冲突错误?ProgressChanged 绝对没有在主进程线程上运行,查看调用堆栈。

那么我假设 Application.Run 会生成一个新线程并使用它运行表单?但文件另有说明。要么我犯了一个愚蠢的错误,要么这里有一些我不明白的地方。

有人有想法吗?

4

2 回答 2

3

我相信进度更改事件在Application.Run第一次调用之前正在运行。如果您不从 启动后台工作Main程序,而是从其中一种表单中启动,您将确保在创建后台工作程序并开始报告进度时消息循环已经存在。

于 2012-05-03T14:45:19.923 回答
2

BackgroundWorker 依赖于设置的当前 SynchronizationContext 才能运行。ProgressChanged 事件作为SendOrPostCallback Delegate实现,正如 msdn 文档中所述,SendOrPostCallback 表示您希望在将消息分派到同步上下文时执行的回调方法。在表单设计器中将 BackgroundWorker 添加到表单会正确设置 SynchronizationContext。在您的情况下,BackgroundWorker 没有分配 SynchronizationContext。

于 2012-05-03T14:46:47.663 回答