c# - 如果后台方法需要 UI,则任务不起作用:调用线程必须是 STA,因为许多 UI 组件都需要这个
问题描述
我有一种执行不同操作的异步方法。
public async void OnClickPublish( )
{
Loader loader = new Loader();
loader.Show();
await Task.Run(() => PublishSlides(loader));
}
private async Task PublishSlides(Loader loader)
{
await loader.Dispatcher.Invoke(async () =>
{
loader.LoaderMessage("Opration 1 start..");
List<SlideProperties> DBList= await Task.Run(() =>
objSlideImg.DBOpration()); //UI Not needed. work nice
var cloudTask = SendToCloudAsync(DBList);
await cloudTask.ContinueWith(task =>
{
if (task.IsFaulted)
{
loader.LoaderMessage(task.Exception.Message + " problem occur in cloud publish");
return;
}
loader.ShowSuccess("broadcasting..");
}, uiScheduler);
}
}
/*PROBLEM OCCUR IN THIS METHOD*/
public async Task<bool> SendToCloudAsync(List<SlideProperties> DBList)
{
**DashboardUI dashboard= new DashboardUI();** /* giving issue The calling thread must be STA, because many UI components require this.*/
dashboard.ShowDashboard()
}
所以当我调用 SendToCloudAsync() 方法时,它会给出问题调用线程必须是 STA,因为许多 UI 组件都需要这个。SendToCloudAsync() 这个方法将显示我的应用程序的仪表板。
解决方案
我强烈建议将 UI 代码与后台代码分开,并让 UI 层“驱动”业务/后台代码。
目前,在后台线程 ( ) 上OnClickPublish
调用,然后立即跳回 UI 线程 ( ) 并在 UI 线程上运行其整个方法体。这并没有完成任何事情——只是在线程之间来回跳跃。PublishSlides
Task.Run
PublishSlides
Dispatcher.Invoke
要正确地将 UI 与后台线程代码分开,有两种主要技术和一种不太常见的技术。
第一个主要技术是使用返回值。与其让一个方法检索/计算数据,然后用数据结果更新 UI,不如让它检索/计算数据并返回它。然后调用线程可以决定检索/计算是否应该在后台线程(Task.Run
)上,然后将数据放在 UI 上。
第二个主要技术是使用进度更新。与其让“工作”方法进入 UI 并直接更新进度,不如使用它IProgress<T>
来报告进度。然后调用方法可以决定“工作”是否应该在后台线程(Task.Run
)上运行,并且它可以传递一个Progress<T>
在 UI 线程上执行进度更新的进度实现(例如,)。
不太常见的技术是从持续运行的后台操作中主动更新 UI。我建议使用SynchronizationContext
它,但是因为代码更复杂并且不适用于这个问题,所以我就停在那里。
这是使用返回值和await
. 确切的详细信息将取决于您的其余代码的详细信息:
public async void OnClickPublish()
{
Loader loader = new Loader();
loader.Show();
PublishSlides(loader);
}
private async Task PublishSlides(Loader loader)
{
loader.LoaderMessage("Opration 1 start..");
List<SlideProperties> DBList = await Task.Run(() => objSlideImg.DBOpration());
try
{
await SendToCloudAsync(DBList);
loader.ShowSuccess("broadcasting..");
}
catch (Exception ex)
{
loader.LoaderMessage(ex.Message + " problem occur in cloud publish");
}
DashboardUI dashboard = new DashboardUI();
dashboard.ShowDashboard();
}
public async Task<bool> SendToCloudAsync(List<SlideProperties> DBList)
{
...
}
推荐阅读
- jsf - 在 Menu 中设置值并在 Dialog 中显示
- c# - 用于 DB 调用的带有 Task.Run 方法的异步等待
- kubernetes - 使 Traefik 将 HTTP BAN 请求路由到与常规 HTTP 请求不同的服务或端口
- java - 如何在不访问更大类型的情况下缩放 Int64 值?
- javascript - JavaScript。在 setTimeout 函数中分配不正确的值
- ruby-on-rails - 有没有办法覆盖production.rb?(初始化程序在 config/environments 文件夹之后运行)
- c++ - AddressSanitizer 识别 std::vector
::push_back 作为 heap-use-after-free 错误的原因 - actions-on-google - 接收 UDP 扫描数据的 TypeError
- python - 将 thorlabs 设备与 pylablib 接口
- python - 使用从 csv 创建的 python 字典