我是一个通过示例学习的 C# 编码人员,但不是很先进,这就是为什么无论 Internet 上的信息量如何,这个问题都完全困扰着我。
我实际上是在创建一个程序,该程序在计时器上反复轮询网站以获取一些信息。在此过程中,将创建一个 WebBrowser 控件以导航到信息(需要进行身份验证)。该程序在启动时运行这一系列事件,然后使用 System.Timers.Timer 设置为每 10 分钟(当然调试时间更少)来执行相同系列的事件,但是当我的 Timer.Elapsed 事件触发该过程时,我得到一个:
ThreadStateException,描述为 ActiveX 控件 '8856f961-340a-11d0-a96b-00c04fd705a2' 无法实例化,因为当前线程不在单线程单元中。
这是我的程序的精简版。
private void Form1_Load(object sender, EventArgs e)
{
GetDataFromWebBrowser();
Set_Auto_Refresh_Timer();
}
private void Set_Auto_Refresh_Timer()
{
System.Timers.Timer TimerRefresh = new System.Timers.Timer(10000);
TimerRefresh.Elapsed += new System.Timers.ElapsedEventHandler(TimerRefresh_Elapsed);
TimerRefresh.AutoReset = true;
TimerRefresh.Start();
}
private void TimerRefresh_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
GetDataFromWebBrowser();
}
private void GetDataFromWebBrowser()
{
WebBrowser wb = new WebBrowser(); <--This is where the error is thrown.
...get web data...
}
我想我有足够的代码来绘制图片。如您所见,当它开始创建另一个 WebBrowser 时,它会抛出错误。
我真的很困惑,我才刚刚开始了解 Threading 的表面,这可能就是我如此困惑的原因。
//我的解决方案/ 我最终将 WebBrowser 创建移出该方法,并将其设为静态以仅重用 WebBrowser 控件。我还将我的 System.Timers.Timer 换成了 System.Threading.Timer。似乎解决了问题。
最佳答案
MSDN documentation for WebBrowser指出:
The WebBrowser class can only be used in threads set to single thread apartment (STA) mode. To use this class, ensure that your Main method is marked with the [STAThread] attribute.
此外,如果您想定期与 UI 控件交互,请将 System.Timers.Timer
更改为 System.Windows.Forms.Timer
。或者,设置 SynchronizingObject您的 System.Timers.Timer
属性到父控件,以强制您的计时器在正确的线程上调用调用。所有 WinForms 控件只能从同一个且唯一的 UI 线程访问。
.NET 的 BCL 中有三种类型的计时器,每种计时器的作用都非常不同。查看这篇 MSDN 文章进行比较:Comparing the Timer Classes in the .NET Framework Class Library (web archive)或者这个 brief comparison table .
关于c# - 定时器和线程的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9076041/