来自有关STAThread的MSDN文章:
表示应用程序的COM线程模型是单线程单元(STA).
(作为参考,这是整篇文章.)
单线程公寓......好吧,我的头脑.另外,我在某处读到,除非你的应用程序使用COM互操作,否则这个属性实际上什么都不做.那究竟它究竟做了什么,以及它如何影响多线程应用程序?多线程应用程序(包括使用Timers到异步方法调用的任何人,而不仅仅是线程池等)都应该使用MTAThread,即使它"只是为了安全"?STAThread和MTAThread实际上做了什么?
我需要在HTML页面中获取有关应用的CSS样式的信息.我使用AxWebBrowser并迭代IHTMLDOMNode.我能够获得所需的所有数据并将代码移动到我的应用程序中.问题是这部分是在后台worker中运行的,我在尝试实例化控件时遇到异常.
AxWebBrowser browser = new AxWebBrowser();
ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated
because the current thread is not in a single-threaded apartment.
Run Code Online (Sandbox Code Playgroud)
有什么方法可以解决这个或其他选项而不是AxWebBrowser?
我想测试一个使用剪贴板(WindowsForms)的应用程序,我也需要在单元测试中使用剪贴板.为了使用它,它应该在STA模式下运行,但由于NUnit TestFixture没有main方法,我不知道在哪里/如何注释它.
在我的WPF应用程序中,我做了一些异步通信(与服务器).在回调函数中,我最终从服务器的结果创建InkPresenter对象.这要求运行的线程是STA,显然它当前不是.因此我得到以下异常:
无法创建在程序集中定义的'InkPresenter'实例[...]调用线程必须是STA,因为许多UI组件都需要这样做.
目前我的异步函数调用是这样的:
public void SearchForFooAsync(string searchString)
{
var caller = new Func<string, Foo>(_patientProxy.SearchForFoo);
caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null);
}
Run Code Online (Sandbox Code Playgroud)
如何进行回调 - 这将创建InkPresenter - 是STA吗?或者在新的STA线程中调用XamlReader解析.
public void SearchForFooCallbackMethod(IAsyncResult ar)
{
var foo = GetFooFromAsyncResult(ar);
var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter; // <!-- Requires STA
[..]
}
Run Code Online (Sandbox Code Playgroud) 我正在创建一个自动测试运行应用程序.在这部分应用程序中,我正在研究一个轮询服务器.它的工作原理是不断轮询Web服务器,以确定何时应运行新的自动化测试(对于我们的GUI应用程序的夜间自动运行).
当轮询服务器看到请求时,它会下载所需的所有信息,然后在后台工作程序中执行测试运行.问题是测试运行的一部分具有Clipboard.Clear()在后台工作线程中发生的OLE,COM和其他调用(例如).发生其中一个调用时,会发生以下异常:
在进行OLE调用之前,必须将当前线程设置为单线程单元(STA)模式.确保您的Main函数标记了STAThreadAttribute.
如何将后台工作线程标记为单线程单元?我的Program.cs中的Main调用显然已经具有该属性.
我有一个需要在STA公寓状态下运行的功能.我不想检查它是否作为STA运行,如果没有生成一个在STA中运行的新线程.
如何检查当前线程运行的公寓状态?
我仍然是C#的新手,尤其是C#中的线程.我正在尝试启动一个需要单线程单元的函数(STAThread)
但我无法编译以下代码:
该函数在一个名为的单独类中如下所示MyClass:
internal static string DoX(string n, string p)
{
// does some work here that requires STAThread
}
Run Code Online (Sandbox Code Playgroud)
我已经尝试了函数顶部的[STAThread]属性,但这不起作用.
所以我试图创建一个新的Thread如下:
Thread t = new Thread(new ThreadStart(MyClass.DoX));
Run Code Online (Sandbox Code Playgroud)
但这不会编译(最好的重载方法有无效的参数错误).然而,在线示例非常相似(这里的示例) 我做错了什么,我怎样才能简单地在新的STA线程中运行函数?
谢谢
使用Visual Studio 创建空WinForms应用程序时,模板STAThread在主应用程序类中具有该属性.
我一直在阅读一些关于它的文档,但我不确定我是否理解它.
我真的有一些问题:
如果我们像这样创建一个线程STA:Thread.SetApartmentState(STA);那么它就不能运行标有[MTAThread]属性的代码.
我们已经[STAThread]在Windows和控制台应用程序中看到过,但我从未见过具有[MTAThread]属性的代码,也不知道哪些.NET库使用此属性.
我的问题是,与具有MTA单元状态(自然.NET线程)的线程相比,将单元状态设置为STA的线程的局限性是什么?
我创建了一个将调用某些COM组件的Windows服务,因此我将[STAThread]标记为Main函数.但是,当计时器触发时,它会报告MTA并且COM调用失败.我怎样才能解决这个问题?
using System;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;
using System.Timers;
namespace MyMonitorService
{
public class MyMonitor : ServiceBase
{
#region Members
private System.Timers.Timer timer = new System.Timers.Timer();
#endregion
#region Construction
public MyMonitor ()
{
this.timer.Interval = 10000; // set for 10 seconds
this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed);
}
#endregion
private void timer_Elapsed (object sender, ElapsedEventArgs e)
{
EventLog.WriteEntry("MyMonitor", String.Format("Thread Model: {0}", Thread.CurrentThread.GetApartmentState().ToString()), EventLogEntryType.Information);
}
#region Service Start/Stop
[STAThread]
public static void Main ()
{
ServiceBase.Run(new MyMonitor());
}
protected override void …Run Code Online (Sandbox Code Playgroud)