我得到的错误“跨线程操作无效:控制‘label1的’从比它创建的线程以外的线程访问。” 当我运行这段代码:
using System;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Timers;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
System.Timers.Timer T = new System.Timers.Timer();
public Form1()
{
InitializeComponent();
T.Elapsed += new ElapsedEventHandler(T_Elapsed);
T.Start();
}
void T_Elapsed(object sender, ElapsedEventArgs e)
{
label1.Text = "This will not work";
}
}
}
我以为事件在同一个线程跑了,因为他们在被触发。
您使用的可能是一种错误的定时器。 尝试的WinForms计时器,它的GUI线程上运行,这样你就不必做调用
我们在NET(Timers.Timer,Threading.Timer和Windows.Forms.Timer)3个定时器类,但只有一个Windows.Forms的有一个Tick事件。
当正常使用(即拖动到设计时的形式或某种形式的代码创建)的事件是主线程上运行,而不会出现你的问题。
因此,它是最有可能创建在另一个线程Timer对象,你应该编辑您的问题向我们展示了如何/在哪里创建它,并告诉我们,如果它是故意的另一个线程。
虽然“接受”的答案是技术上正确(这将解决这个问题)这不回答这个问题。
答案是使用
void T_Elapsed(object sender, ElapsedEventArgs e)
{
this.BeginInvoke(new MethodInvoker(delegate(){
label1.Text = "This will work";
}));
}
http://jaysonknight.com/blog/archive/2007/02/14/using-anonymous-methods-for-control-invoke-control-begininvoke.aspx
你是否记得使用InvokeRequired ? 它可以让你更新从计时器线程UI线程上的UI元素。
我假设你是在谈论一个WinForms应用程序。
当试图从另一个线程更新表单元素(它生活在UI线程上),则需要使用Control.Invoke或Control.BeginInvoke 。 你传递一个委托要调用(或传递一个匿名方法),然后该委托被调用UI线程,而不是调用线程的方法。
是的,事件在由此引发他们在同一个线程执行。 它只是恰巧, System.Timers.Timer
使用ThreadPool
默认为提高线程时Elapsed
事件。 使用SynchronizingObject
属性使Elapsed
事件处理程序的托管目标对象,而不是线程上执行。
public partial class Form1 : Form
{
System.Timers.Timer T = new System.Timers.Timer();
public Form1()
{
InitializeComponent();
T.Elapsed += new ElapsedEventHandler(T_Elapsed);
T.SynchronizingObject = this;
T.Start();
}
void T_Elapsed(object sender, ElapsedEventArgs e)
{
label1.Text = "This will not work";
}
}
如果你这样做异步(这听起来像你是),请确保你赶上在事件处理程序或回调例外。 如果后台线程抛出一个异常,它会崩溃的应用程序。 这是最常见的原因是我见过的这种行为。
我不是一个WinForm开发。 但我听说您正在使用的东西regararding Timer类。 我想你可能要设置这些属性和检查。
T.Interval = 5000; //in Mili Seconds
T.Enabled = true;