WPF Dispatcher Thread Freeze主窗口

Rho*_*nin 1 c# wpf multithreading task dispatcher

而不是在后台工作 - 这段代码仍然冻结我的程序:

private void button_Click(object sender, RoutedEventArgs e)
{
    this.Dispatcher.BeginInvoke(new Action(() =>
    {
        Thread.Sleep(5000);
        label.Content = "Done";
    }), DispatcherPriority.Normal);
}
Run Code Online (Sandbox Code Playgroud)

我试过Thread/Tasks,线程示例:

private void button_Click(object sender, RoutedEventArgs e)
{
    var t = new Thread(new ThreadStart(runtask));
    t.Start();
}

private void runtask()
{
    this.Dispatcher.BeginInvoke(new Action(() =>
    {
        Thread.Sleep(5000);
        label.Content = "Done";
    }), DispatcherPriority.Normal);
}
Run Code Online (Sandbox Code Playgroud)

任务示例:

private void button_Click(object sender, RoutedEventArgs e)
{
    Task.Run(() =>
    {
        Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() =>
        {
            Thread.Sleep(5000);
            label.Content = "Done";
        }));
    });
}
Run Code Online (Sandbox Code Playgroud)

我的节目仍然冻结.有什么建议?

Mas*_*aus 7

文件中的Dispatcher类:

提供用于管理线程的工作项队列的服务.

文件Dispatcher.BeginInvoke:

与创建Dispatcher的线程上的指定参数异步执行指定的委托.

这里"异步"是指辅助线程,而不是主要线程.因为主要的一个由主Dispatcher拥有.这意味着每个Dispatcher的调用InvokeBeginInvoke来自任何Thread的调用都会将调用的Action放入主线程必须执行的操作队列中,但从主线程的角度来看,它们将同步执行,一个另一个.

例如,如果你把3动作就像Thread.Sleep(1000);在10毫秒的调度程序,是否符合InvokeBeginInvoke从是否线程,该调度程序将在UI线程同步执行了3动作,所以他们将采取一共有3000毫秒.

也许有关文档BeginInvoke可能写得更好,例如:

在创建Dispatcher的线程上执行具有指定参数的指定委托.从调用线程的角度来看,指定的委托是异步执行的.

现在...... Invoke还是BeginInvoke

使用Invoke,辅助线程对Dispatcher说:让我们在主线程上执行它,并且在线程的工作完成之前不敢返回.然后我才会继续.

例如,如果你这样写:

this.Dispatcher.Invoke(new Action(() =>
    {
        Thread.Sleep(5000);
        Debug.WriteLine("After Sleep");
    }));
Debug.WriteLine("Continuation on secondary Thread");
Run Code Online (Sandbox Code Playgroud)

控制台将在~5000毫秒后打印:

"睡眠后"

"继续使用辅助线程"

使用BeginInvoke,相反,主题是说:"哎,调度,排队此操作在主线程,但尽快恢复,所以我可以立即继续我的工作".

在这种情况下,控制台将立即打印:

"继续使用辅助线程"

大约5000毫秒后:

"睡眠后"


现在,如果您的目的是在后台执行一些繁重的操作,您应该了解.NET 4.5和C#5.0中提供的async/await模式.

在你的例子中,我会写:

private async void button_Click(object sender, RoutedEventArgs e)
{
    await Task.Delay(5000); // await a heavy operation executed in background

    label.Content = "Done"; // control back to the UI Thread that executes this
}
Run Code Online (Sandbox Code Playgroud)

  • @Rhonin,这就是 Bindings 可以帮助您的地方。你有一个视图。该视图与一个 ViewModel 相结合。ViewModel 有一个属性,“string LabelContent”,绑定到“Label”的“Content”属性。然后,您可以从任何线程更新“LabelContent”:绑定将负责将其分派到 UI 线程,避免 CrossThreadException。WPF太美了…… (2认同)