[因此,我目前在下面的这段代码中,有一个后台工作程序调用showdialog()。但是,我认为UI无法在后台线程上更新,因此对话框如何显示?对话框实际上是否在UI线程上打开了吗?会发生什么?
public partial class ProgressDialog : Window
{
BackgroundWorker _worker;
public BackgroundWorker Worker
{
get { return _worker; }
}
public void RunWorkerThread(object argument, Func<object> workHandler)
{
//store reference to callback handler and launch worker thread
workerCallback = workHandler;
_worker.RunWorkerAsync(argument);
//display modal dialog (blocks caller)
//never returns null, but is a nullable boolean to match the dialogresult property
ShowDialog();
}
我已经得到建议,我只是运行代码并检查,但是如何检查显示对话框窗口是在新线程上还是在后台线程本身上打开的?不知道我将如何检查。
无论如何,这只是一篇文章,旨在帮助我理解代码中实际发生的事情。
无论如何,最终还是更多地了解了评论,所以我想我了解正在发生的一切。我的大多数实际问题不是由该对话框引起的,它们是由于在控件绑定到非UI线程时更新了来自非UI线程的可观察集合所引起的。
从技术上讲,您并不是在更改主线程上的属性,而只是创建另一个对象的实例。
但是如果您对方法ShowDialog()进行详细说明,可能会有所帮助。
我也有从非UI线程调用ShowDialog()的问题。我的回答是它取决于调用ShowDialog()的线程。如果在此线程启动之前为该线程设置ApartamentState属性,则所有操作都将如从UI线程调用一样。我最终得到了这样的代码:
private async void button1_Click(object sender, EventArgs e)
{
var foo = new Foo();
// MessageBox.Show(foo.DirPath) - this works as a charm but
// if, it is called from non UI thread needs special handling as below.
await Task.Run(() => MessageBox.Show(foo.DirPath));
}
public class Foo
{
private string dirPath;
public string DirPath
{
get
{
if (dirPath == null)
{
var t = new Thread(() =>
{
using (var dirDialog = new FolderBrowserDialog())
{
if (dirDialog.ShowDialog() == DialogResult.OK)
dirPath = dirDialog.SelectedPath;
}
}
);
t.IsBackground = true;
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
return dirPath;
}
set
{
dirPath = value;
}
}
}
我不确定,但我认为showDialog不会创建仅显示该对象的对象。因此,当您说ShowDialog时,它仅指示显示。因此它将在UI线程而不是backgroundworker上运行(不确定)