我的演示者课程中BackGroundWorker
doWork
方法存在问题。
我的第一个问题是为什么Thread.CurrentThread.Join()
不起作用。
第一次点击该行后代码中断。我能做的只是设定一个计时器......
我的第二个问题是为什么CheckDocumentError()
抛出“ 调用线程无法访问此对象,因为不同的线程拥有它 ”即使我正在调用它与Dispatcher。
我在这里缺少什么? 相关信息是设置Document属性和CheckDocumentError方法都更新UI。
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
foreach (KeyValuePair<string, Stream> pair in (Dictionary<string, Stream>)e.Argument)
{
Document = new Document(pair.Value);
Thread.CurrentThread.Join(5000);
Dispatcher.CurrentDispatcher.Invoke((Action)(() =>
{
CheckDocumentError(Document);
}));
}
}
答案 0 :(得分:1)
如果要在后台线程中执行某些长时间运行的操作,则使用BackgroundWorker
class,以便UI不会冻结。您不应该手动与任何Thread
对象进行交互,因为这些都是在幕后为您完成的。请尝试使用此代码:
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
foreach (KeyValuePair<string, Stream> pair in (Dictionary<string, Stream>)e.Argument)
{
Document = new Document(pair.Value);
CheckDocumentError(Document);
}
}
有关使用BackgroundWorker
的更多帮助,请参阅MSDN上的链接页面。
更新&gt;&gt;&gt;
好的,我刚才注意到你问题中的一行:相关信息是设置Document属性和CheckDocumentError方法都更新UI。
您无法从DoWork
方法更新用户界面,因为它在后台Thread
上运行。您需要在长时间运行的部分中使用<{1}} 内部该方法才能使其正常工作。
答案 1 :(得分:1)
很难弄清楚你究竟想做什么。以下是如何从工作线程中以实际更新UI线程的方式启动UI更新,从而避免错误:
public partial class MainWindow : Window
{
BackgroundWorker Worker;
public MainWindow()
{
InitializeComponent();
Worker = new BackgroundWorker();
Worker.DoWork += new DoWorkEventHandler(worker_DoWork);
Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
Worker.RunWorkerAsync("param");
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
tb.Dispatcher.Invoke((Action)(() =>
{
tb.Text = "doing work: " + (e.Argument as string);
}));
Thread.Sleep(5000);
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
tb.Dispatcher.Invoke((Action)(() =>
{
tb.Text = "finished work";
}));
}
}
请注意,由于我从后台线程更新UI,我不使用CurrentDispatcher,我使用负责拥有我正在更新的控件的线程的调度程序(tb是XAML文件中的TextBox)窗口)。
我不知道要替换你的CurrentThread.Join是什么,因为我不明白代码的那一部分。但是CurrentThread.Join肯定是错的,它基本上是一个线程上自我造成的死锁。
答案 2 :(得分:0)
您正在后台工作程序的线程中创建类型Document
的实例。然后尝试从Dispatcher的线程访问它。这导致“调用线程无法访问此对象,因为另一个线程拥有它”错误,因为工作线程现在拥有类型Document
的实例。在Dispatcher的线程中创建实例。