如何在任务中关闭 WPF window
How to close WPF window inside of a Task
我需要运行一个任务来检查连接。
我的 windows 不应该在此检查期间被冻结。
所以我开始任务,并在任务结束时关闭我的 window。
但是这个 returns 一个例外:InvalidOperationException:'The calling thread cannot access this object because another thread owns it'.
像这样:
private void Window_ContentRendered(object sender, System.EventArgs e)
{
Task.Run(() =>
{
ConnectionState = false;
if (NetworkTools.CheckGlobalConnection() == (ConnectionStatus.NetworkConnectionSuccess, ConnectionStatus.ServerConnectionSuccess))
{
ConnectionState = true;
}
this.Close();
});
}
如何在任务结束时关闭我的 window 而不会冻结它并且不会出现此异常?
(我有一个无限旋转的进度条)
使用 Dispatcher
在唯一 UI 线程上排队 window 关闭逻辑。
就像是
Dispatcher.Invoke(
() =>
{
// close window here
});
无论什么作为委托传递给 .Invoke(...)
,都会在 UI 线程上调用,因此有权访问所有 UI 元素。这是处理非 UI 线程中的 UI 突变的常见(也是唯一正确的)方法。
或者您可以只使用 async await。 Task.Run
将卸载并且等待将在当前 SynchronizationContext 上创建一个延续。反过来将控制权交还给 UI 并关闭正确的线程。
private async void Window_ContentRendered(object sender, System.EventArgs e)
{
await Task.Run(() =>
{
ConnectionState = false;
if (NetworkTools.CheckGlobalConnection() == (ConnectionStatus.NetworkConnectionSuccess, ConnectionStatus.ServerConnectionSuccess))
ConnectionState = true;
});
this.Close();
}
另外如前所述,Calling ConfigureAwait(false)
在这种情况下不是正确的做法
作为替代方法,您可以使用 ContinueWith
private void Window_ContentRendered(object sender, System.EventArgs e)
{
Task.Run(() =>
{
// Your code
}).ContinueWith((tsk) =>
{
this.Close();
}, TaskScheduler.FromCurrentSynchronizationContext());
}
我需要运行一个任务来检查连接。
我的 windows 不应该在此检查期间被冻结。
所以我开始任务,并在任务结束时关闭我的 window。
但是这个 returns 一个例外:InvalidOperationException:'The calling thread cannot access this object because another thread owns it'.
像这样:
private void Window_ContentRendered(object sender, System.EventArgs e)
{
Task.Run(() =>
{
ConnectionState = false;
if (NetworkTools.CheckGlobalConnection() == (ConnectionStatus.NetworkConnectionSuccess, ConnectionStatus.ServerConnectionSuccess))
{
ConnectionState = true;
}
this.Close();
});
}
如何在任务结束时关闭我的 window 而不会冻结它并且不会出现此异常? (我有一个无限旋转的进度条)
使用 Dispatcher
在唯一 UI 线程上排队 window 关闭逻辑。
就像是
Dispatcher.Invoke(
() =>
{
// close window here
});
无论什么作为委托传递给 .Invoke(...)
,都会在 UI 线程上调用,因此有权访问所有 UI 元素。这是处理非 UI 线程中的 UI 突变的常见(也是唯一正确的)方法。
或者您可以只使用 async await。 Task.Run
将卸载并且等待将在当前 SynchronizationContext 上创建一个延续。反过来将控制权交还给 UI 并关闭正确的线程。
private async void Window_ContentRendered(object sender, System.EventArgs e)
{
await Task.Run(() =>
{
ConnectionState = false;
if (NetworkTools.CheckGlobalConnection() == (ConnectionStatus.NetworkConnectionSuccess, ConnectionStatus.ServerConnectionSuccess))
ConnectionState = true;
});
this.Close();
}
另外如前所述,Calling ConfigureAwait(false)
在这种情况下不是正确的做法
作为替代方法,您可以使用 ContinueWith
private void Window_ContentRendered(object sender, System.EventArgs e)
{
Task.Run(() =>
{
// Your code
}).ContinueWith((tsk) =>
{
this.Close();
}, TaskScheduler.FromCurrentSynchronizationContext());
}