[英]How can you pump a STA Thread in a non-WinForms assembly?
Hans 给出了这个关于抽取 STA 线程的好答案: https://stackoverflow.com/a/21684059/197229
using System;
using System.Threading;
using System.Windows.Forms;
class STAThread : IDisposable {
public STAThread() {
using (mre = new ManualResetEvent(false)) {
thread = new Thread(() => {
Application.Idle += Initialize;
Application.Run();
});
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
mre.WaitOne();
}
}
public void BeginInvoke(Delegate dlg, params Object[] args) {
if (ctx == null) throw new ObjectDisposedException("STAThread");
ctx.Post((_) => dlg.DynamicInvoke(args), null);
}
public object Invoke(Delegate dlg, params Object[] args) {
if (ctx == null) throw new ObjectDisposedException("STAThread");
object result = null;
ctx.Send((_) => result = dlg.DynamicInvoke(args), null);
return result;
}
protected virtual void Initialize(object sender, EventArgs e) {
ctx = SynchronizationContext.Current;
mre.Set();
Application.Idle -= Initialize;
}
public void Dispose() {
if (ctx != null) {
ctx.Send((_) => Application.ExitThread(), null);
ctx = null;
}
}
private Thread thread;
private SynchronizationContext ctx;
private ManualResetEvent mre;
}
But it relies on calls like Application.Run which is a Windows Forms class, I don't think I want in a non-UI static library.
那么有没有办法调整它,或者它甚至可以按原样使用?
您可以使用 Stephen Cleary 的Nito.AsyncEx.Context
nuget 中的AsyncContextThread
。 来自其github 描述
AsyncContextThread 提供可用于在该线程上安排任务的属性。
nuget 包含SynchronizationContext
的自定义实现,因此代码可以很容易地重写,例如:
using System;
using System.Threading;
using Nito.AsyncEx;
class STAThread : IDisposable
{
public STAThread()
{
ctx = new AsyncContextThread();
}
public void BeginInvoke(Delegate dlg, params Object[] args)
{
ctx.Context.SynchronizationContext
.Post((_) => dlg.DynamicInvoke(args), null);
}
public object Invoke(Delegate dlg, params Object[] args)
{
object result = null;
ctx.Context.SynchronizationContext
.Send((_) => result = dlg.DynamicInvoke(args), null);
return result;
}
public void Dispose()
{
ctx.JoinAsync().GetAwaiter().GetResult();
ctx.Dispose();
}
private readonly AsyncContextThread ctx;
}
顺便说一句,从这篇 MSDN 文章中,并非SynchronizationContext
的所有实现都保证委托将在特定线程上执行,而 WinForms 和 WPF SynchronizationContext
保证默认和 ASP.NET 不保证。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.