【发布时间】:2016-06-21 19:38:28
【问题描述】:
我有一个简单的控制台应用程序,可以向标准输出报告进度。例如:
static void Main(string[] args)
{
for (int i = 0; i <= 100; i += 10)
{
Console.WriteLine(i);
System.Threading.Thread.Sleep(1000);
}
}
产生这个输出:
0
10
20
30
40
50
60
70
80
90
100
我想通过 .NET Process 调用此应用程序,并异步更新 WPF 控件(特别是 ProgressBar):
private void Run()
{
Process process = new Process();
process.StartInfo.FileName = "ConsoleApplication1.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
if (e.Data != null)
{
Console.WriteLine(e.Data);
ProgressBar.Value = double.Parse(e.Data);
}
});
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
process.Close();
}
当我运行它时,它会毫无问题地写入控制台,但可以理解的是抱怨试图从不同的线程访问 ProgressBar,所以我用调用来包装它:
Application.Current.Dispatcher.Invoke(() =>
{
ProgressBar.Value = double.Parse(e.Data);
});
但是,它在调用时会冻结。大概是发生了死锁,虽然我不明白为什么。
环顾四周,似乎 Process.SynchronizingObject 旨在解决这些情况,但我无法从 WPF 中看到如何使用它,因为控件没有 ISynchronizeInvoke 属性。
【问题讨论】:
-
如果您在应用程序初始化时声明
public System.Windows.Threading.Dispatcher dispatch = System.Windows.Threading.Dispatcher.CurrentDispatcher;之类的内容并使用该调度程序,它会改变行为吗? -
@pay:没有变化,不管我把
dispatch放在MainWindow还是App。 -
嗯,所以即使在UI线程上创建了dispatcher,它还是死锁了?也许也可以从该事件处理程序的内部删除。
-
@pay:从事件处理程序内部删除什么?
-
致电
Invoke