WPF Dispatcher Thread Freeze主窗口

时间:2017-09-16 11:59:55

标签: 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);
}

我尝试使用线程/任务,线程示例:

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);
}

任务示例:

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

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

2 个答案:

答案 0 :(得分:7)

来自Dispatcher班级的documentation

  

提供管理线程工作项队列的服务。

来自Dispatcher.BeginInvoke的{​​{3}}:

  

使用创建Dispatcher的线程上的指定参数异步执行指定的委托。

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

例如,如果你在Dispatcher上放置了10 {10}之内的3个Action,无论是Thread.Sleep(1000);还是Invoke,还是来自Thread,那个Dispatcher会将UI线程设置为同步执行3 Action,总共需要3000 ms。

也许有关BeginInvoke的文档可以更好地编写,例如:

  

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

现在...... BeginInvokeInvoke

使用BeginInvoke,辅助线程向Dispatcher说:让我们在主线程上执行此操作,并且在线程的作业完成之前不敢返回。然后我才会继续

例如,如果你这样写:

Invoke

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

  

“睡眠后”

     

“继续使用辅助线程”

使用this.Dispatcher.Invoke(new Action(() => { Thread.Sleep(5000); Debug.WriteLine("After Sleep"); })); Debug.WriteLine("Continuation on secondary Thread"); ,而线程正在说:“嘿,Dispatcher,在主线程上对此操作进行排队,但是尽快返回,以便我可以立即继续我的工作”

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

  

“继续使用辅助线程”

大约5000毫秒后:

  

“睡眠后”

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

在你的例子中,我会写:

BeginInvoke

答案 1 :(得分:-1)

如果您的UI访问是最后一种方法,则可以使用此小扩展名。

https://mitsufu.wordpress.com/2015/08/03/dispatcher-switchto/

private void Button_Click(object sender, RoutedEventArgs e)
{
    Task.Run(async () =>
    {
        //heavy background operation
        await Dispatcher.SwitchTo();
        Title = "ok";
    });
}