C# 解决调用线程无法访问此对象,因为另一个线程在不使用Dispatcher的情况下拥有该对象

C# 解决调用线程无法访问此对象,因为另一个线程在不使用Dispatcher的情况下拥有该对象,c#,wpf,C#,Wpf,有没有办法在不使用dispatcher的情况下解决此错误“调用线程无法访问此对象,因为另一个线程拥有它”,因为dispatcher会在代码处理时间较长时导致UI冻结?还有其他方法吗?在不导致UI冻结的情况下否,您必须更新UI线程上的UIElement,如错误所示 是的,除了使用Dispatcher之外,还有其他方法可以在UI线程上运行某些东西,但是他们喜欢Dispatcher仍然运行您想要在UI线程上运行的任何东西,因此仍然会冻结UI 如果您使用的是C#5和.NET 4.5或更高版本,您可以轻松

有没有办法在不使用dispatcher的情况下解决此错误“调用线程无法访问此对象,因为另一个线程拥有它”,因为dispatcher会在代码处理时间较长时导致UI冻结?还有其他方法吗?在不导致UI冻结的情况下

否,您必须更新UI线程上的UIElement,如错误所示

是的,除了使用
Dispatcher
之外,还有其他方法可以在UI线程上运行某些东西,但是他们喜欢
Dispatcher
仍然运行您想要在UI线程上运行的任何东西,因此仍然会冻结UI

如果您使用的是C#5和.NET 4.5或更高版本,您可以轻松地运行长时间运行的进程,而无需阻塞UI线程,然后当它完成时,使用
async
wait
关键字在UI线程上继续运行(而不必担心其工作方式):

    private async Task<string> SimLongRunningProcessAsync()
    {
        await Task.Delay(2000);
        return "Success";
    }

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        button.Content = "Running...";
        var result = await SimLongRunningProcessAsync();
        button.Content = result;
    }

如果您使用的是.NET 4.0或更高版本,则可以使用来生成干净的异步代码。此功能直接内置于4.5中,对于4.0,Microsoft(
Microsoft.Bcl.Async
)提供了一个NuGet软件包来启用此功能

例如,用户单击一个按钮,您希望做一些可能需要一些时间的事情,然后向用户报告

// Notice how this method is marked 'async', this allows the 'await' keyword
async void OnButtonClicked(object sender, EventArgs e)
{
   var button = sender as Button;

   button.IsEnabled = false;
   button.Text = "Calculating...";

   int result = await DoSomeWork();

   button.IsEnabled = true;
   button.Text = "Calculate";
}

// This is an asynchronous method that returns an integer result
Task<int> DoSomeWork()
{
   // Do some lengthy computation here, will be run on a background thread
   return 42;
}
//注意这个方法是如何标记为“async”的,这允许使用“await”关键字
异步void OnButtonClicked(对象发送方,事件参数e)
{
var按钮=发送方为按钮;
button.IsEnabled=false;
button.Text=“计算…”;
int result=等待DoSomeWork();
button.IsEnabled=true;
button.Text=“计算”;
}
//这是一个异步方法,返回整数结果
任务DoSomeWork()
{
//在这里做一些冗长的计算,将在后台线程上运行
返回42;
}
或者,您可以使用其他机制,如
BackgroundWorker
类,或带有回调的。这些都很好,但是
异步
/
等待
模式更可取


如果您有选择,请选择目标.NET 4.5(Win7+)。如果您还必须支持Windows XP,请以.NET 4.0为目标,并使用适用于
Microsoft.Bcl.Async

的NuGet软件包,让“更长时间进程”在后台/工作线程上运行,而不是在UI线程上运行。只有在最终计算出结果后,才可以通过dispatcher调用UI,将结果分配给相应的UI元素。谢谢,建议将尝试应用到我的解决方案中。您可以为这种方法提供一些示例代码吗?什么方法?根据您的问题,我推断您已经知道如何使用Dispatcher,还是我弄错了?您使用的是.NET的哪个版本?如果您使用的是4.0+,我强烈建议您使用
async
/
wait
模式来分离后台任务和与UI相关的代码。如果您使用的是4.0,则Microsoft提供的
Bcl.Async
NuGet软件包会添加此功能,因为它被烘焙到4.5+。Async和await关键字在.Net 4.0中不存在。它们直到.Net 4.5+才出现(不能单独按“回车”键在该编辑中开始新行!)抱歉。错过了关于NuGet软件包的细节。。。但这不会是特快版(我使用的是异步事件处理程序和相同的错误。在可等待调用(例如
int result=wait DoSomeWork().ConfigureAwait(false))之后,我的问题在删除
.ConfigureAwait(false)
后得到解决
。第一个示例不起作用,因为按钮单击方法不是异步的,因此不能使用wait命令。@使用
.NET 4.5或更高版本的
标记您的响应非常好。您解决了我的类似问题。感谢您分享您的知识(从而帮助他人)。
// Notice how this method is marked 'async', this allows the 'await' keyword
async void OnButtonClicked(object sender, EventArgs e)
{
   var button = sender as Button;

   button.IsEnabled = false;
   button.Text = "Calculating...";

   int result = await DoSomeWork();

   button.IsEnabled = true;
   button.Text = "Calculate";
}

// This is an asynchronous method that returns an integer result
Task<int> DoSomeWork()
{
   // Do some lengthy computation here, will be run on a background thread
   return 42;
}