Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF调度程序线程冻结主窗口_C#_Wpf_Multithreading_Task_Dispatcher - Fatal编程技术网

C# WPF调度程序线程冻结主窗口

C# WPF调度程序线程冻结主窗口,c#,wpf,multithreading,task,dispatcher,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)
{
    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";
        }));
    });
}
但我的程序仍然冻结。有什么建议吗?

来自
调度程序
类的:

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

从Dispatcher.BeginInvoke的

在创建调度程序的线程上,使用指定的参数异步执行指定的委托

这里“异步”指的是辅助线程,而不是主线程。因为主调度器属于主调度器。这意味着,无论来自哪个线程,对该调度器的
Invoke
BeginInvoke
的每次调用都会将被调用的操作放入主线程必须执行的操作队列中,但从主线程的角度来看,它们将一个接一个地同步执行

例如,如果您放置3个动作,如
Thread.Sleep(1000)
在调度程序上的10毫秒内,无论是使用
Invoke
还是
BeginInvoke
,该调度程序都将使UI线程同步执行3个操作,因此总共需要3000毫秒

也许关于
BeginInvoke
的文档可以写得更好,比如:

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

现在<代码>调用
开始调用

使用
Invoke
,次线程对调度程序说:让我们在主线程上执行此操作,在线程的作业完成之前,不敢返回。只有到那时,我才会继续

例如,如果您编写以下内容:

this.Dispatcher.Invoke(new Action(() =>
    {
        Thread.Sleep(5000);
        Debug.WriteLine("After Sleep");
    }));
Debug.WriteLine("Continuation on secondary Thread");
控制台将在约5000毫秒后打印:

“睡后”

“在次线程上继续”

相反,使用
BeginInvoke
,线程会说:“嘿,Dispatcher,在主线程上将此操作排队,但请尽快返回,以便我可以立即继续我的工作。”

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

“在次线程上继续”

约5000 ms后:

“睡后”


现在,如果您的目的是在后台执行一些繁重的操作,那么您应该了解异步/等待模式,该模式可从.NET4.5和C#5.0获得

在你的例子中,我会写:

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
}
调度程序
类的

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

从Dispatcher.BeginInvoke的

在创建调度程序的线程上,使用指定的参数异步执行指定的委托

这里“异步”指的是辅助线程,而不是主线程。因为主调度器属于主调度器。这意味着,无论来自哪个线程,对该调度器的
Invoke
BeginInvoke
的每次调用都会将被调用的操作放入主线程必须执行的操作队列中,但从主线程的角度来看,它们将一个接一个地同步执行

例如,如果您放置3个动作,如
Thread.Sleep(1000)
在调度程序上的10毫秒内,无论是使用
Invoke
还是
BeginInvoke
,该调度程序都将使UI线程同步执行3个操作,因此总共需要3000毫秒

也许关于
BeginInvoke
的文档可以写得更好,比如:

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

现在<代码>调用
开始调用

使用
Invoke
,次线程对调度程序说:让我们在主线程上执行此操作,在线程的作业完成之前,不敢返回。只有到那时,我才会继续

例如,如果您编写以下内容:

this.Dispatcher.Invoke(new Action(() =>
    {
        Thread.Sleep(5000);
        Debug.WriteLine("After Sleep");
    }));
Debug.WriteLine("Continuation on secondary Thread");
控制台将在约5000毫秒后打印:

“睡后”

“在次线程上继续”

相反,使用
BeginInvoke
,线程会说:“嘿,Dispatcher,在主线程上将此操作排队,但请尽快返回,以便我可以立即继续我的工作。”

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

“在次线程上继续”

约5000 ms后:

“睡后”


现在,如果您的目的是在后台执行一些繁重的操作,那么您应该了解异步/等待模式,该模式可从.NET4.5和C#5.0获得

在你的例子中,我会写:

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
}

如果用户界面访问是方法的最后一步,那么可以使用这个小扩展


如果用户界面访问是方法的最后一步,那么可以使用这个小扩展


是什么让你认为
BeginInvoke
会在后台运行它?从文档中如果您调用Invoke,您实际上处于主线程上。@rhon在文档中表示从调用线程的角度来看它是异步的。从UI线程的角度来看,这绝对是一个同步操作。是的,确切地说……是什么让你认为
BeginInvoke
在后台运行它?从文档中如果您调用Invoke,您实际上处于主线程上。@rhon在文档中表示从调用线程的角度来看它是异步的。从UI线程的角度来看,这绝对是一个同步操作。是的,没错……Async/Wait听起来不错,但如果我想更改UI,则需要在代码内部使用dispatcher