所以我目前在下面有这个代码,它有一个后台工作者调用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线程更新可观察集合而引起的。
答案 0 :(得分:0)
从技术上讲,您不是在创建另一个对象的实例时更改主线程上的属性。
但是如果你在方法ShowDialog()上详细说明一下,它会有所帮助。
答案 1 :(得分:0)
从非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;
}
}
}
答案 2 :(得分:-2)
我不确定但我认为showDialog不会创建仅显示它的对象。所以,当你说ShowDialog它只告诉显示。因此它将在UI线程而不是backgroundworker上运行 (不确定)