通过实例和它们的使用,有人可以帮助我理解:
使用Thread非常简单
Thread thread = new Thread(MethodWhichRequiresSTA);
thread.SetApartmentState(ApartmentState.STA);
Run Code Online (Sandbox Code Playgroud)
如何使用WPF应用程序中的任务完成相同的操作?这是一些代码:
Task.Factory.StartNew
(
() =>
{return "some Text";}
)
.ContinueWith(r => AddControlsToGrid(r.Result));
Run Code Online (Sandbox Code Playgroud)
我收到了一个InvalidOperationException
调用线程必须是STA,因为许多UI组件都需要这个.
我有一个简单的默认 Windows 桌面窗体,Form1带有一个按钮btn_Go作为测试。
我想运行多个并行的 WebView2 实例并处理渲染页面中的 html 代码。为了并行运行 WebView2,我使用 SemaphoreSlim(设置为并行 2)。另一个 SemaphoreSlim 用于等待 WebView2 渲染文档(有一些时间延迟)。
但我的代码落在await webBrowser.EnsureCoreWebView2Async();. WebView2实例中调试器的内部异常webBrowser是:
{"Cannot change thread mode after it is set. (Exception from HRESULT: 0x80010106 (RPC_E_CHANGED_MODE))"} System.Exception {System.Runtime.InteropServices.COMException}
如何并行多次调用 WebView2 并处理所有 url?
完整演示代码:
using Microsoft.Web.WebView2.WinForms;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WebView2Test
{
public partial class Form1 : Form
{
public Form1() { InitializeComponent(); }
private void btn_Go_Click(object sender, EventArgs e) …Run Code Online (Sandbox Code Playgroud) 当我重构一些旧的 C# 代码以使用该库生成文档时Office.Interop,我发现了这一点,因为它使用了 UI 上下文。当从它调用函数时它会阻塞它
例如:
private void btnFooClick(object sender, EventArgs e)
{
bool documentGenerated = chckBox.Checked ? updateDoc() : newDoc();
if(documentGenerated){
//do something
}
}
Run Code Online (Sandbox Code Playgroud)
我决定更改它以减少阻塞 UI:
private async void btnFooClick(object sender, EventArgs e)
{
bool documentGenerated; = chckBox.Checked ? updateDoc() : newDoc();
if(chckBox.Checked)
{
documentGenerated = await Task.Run(() => updateDoc()).ConfigureAwait(false);
}
else
{
documentGenerated = await Task.Run(() => newDoc()).ConfigureAwait(false);
}
if(documentGenerated){
//do something
}
}
Run Code Online (Sandbox Code Playgroud)
它抛出了这个错误:
Current thread must be set to single thread apartment (STA) …Run Code Online (Sandbox Code Playgroud) 我想模仿这段代码:
Task t = Task.Factory.StartNew(...)
t.Wait()
Run Code Online (Sandbox Code Playgroud)
根据这个问题,任务无法设置公寓状态.可以使用Threads设置Apartment state,但我需要在Tasks中使用Wait功能.有没有办法使用Threads模拟Wait()函数?
我在单独的线程中运行一些代码,这可能会引发异常(毕竟,代码倾向于这样做)。该线程将从主线程(GUI)派生,因此最终必须在此处理异常(例如,设置错误消息文本块)。我有两种解决方案,但都不允许在GUI线程中直接捕获异常。
注:我不能用这样的东西 Task 和 BackgroundWorker (至少不开箱),因为我需要能够改变 ApartmentState 线程的。
这是我想要的:
var thread = new Thread(() =>
{
// Code which can throw exceptions
});
try
{
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
MethodThatAwaitsThread(thread);
}
catch
{
// Exception handling in the GUI thread
}
Run Code Online (Sandbox Code Playgroud)
这是行不通的,因为异常永远不会离开线程。我知道它不能随时离开线程,但是我可以等待线程结束然后捕获它。
这是我当前的解决方案,它利用Dispatcher与GUI线程进行通信:
var thread = new Thread(() =>
{
try
{
// Code which can throw exceptions
Dispatcher.Invoke(UpdateGuiAsSuccess);
}
catch (Exception ex)
{
Dispatcher.Invoke(UpdateGuiAsError);
}
}
Run Code Online (Sandbox Code Playgroud)
另一种解决方案是将Exceptionin 存储在对象中,然后在之后显式检查它。但这冒着人们忘记检查异常的风险:
Exception ex = null;
var thread = new Thread(() …Run Code Online (Sandbox Code Playgroud)