3

出现错误:跨线程操作无效:控件'label1'从创建它的线程以外的线程访问。

代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        string CONNECTING = "Connecting to server...";
        string GETTING_DATA = "Getting data...";
        string CONNECT_FAIL = "Failed to connect!";
        string CONNECT_SUCCESS = "Connection established!";

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Thread t1 = new Thread(run);
            t1.Start();
        }

        public void run() {
            label1.Text = CONNECTING;
        }
    }
}

我该如何正确解决这个问题?我试过使用CheckForIllegalCrossThreadCalls = false;,但这显然会导致错误。

我还想知道如何停止线程,因为在该函数之外无法再访问它。

提前致谢!

4

2 回答 2

6

尝试使用 BeginInvoke:

public void run() 
{
    label1.BeginInvoke(new Action(() =>
    {
        label1.Text = CONNECTING;
    }));
}

只有 UI 线程可以更新 Windows 窗体应用程序中的 UI 元素。其他线程需要使用 BeginInvoke 来更新 UI。

原始:我认为这是一个 WPF 应用程序,并说要使用 this.Dispatcher,但 Dispatcher 不在 Windows 窗体应用程序中。

于 2013-07-25T23:27:41.693 回答
4

从不同线程访问控件

你只能从它创建的线程中WinForms App直接访问 a 。Control要执行此类任务,您需要使用控件的InvokeRequired属性来查看是否必须使用Invoke才能强制从原始线程调用操作。

可以从包括原始线程在内的任何线程访问的公共方法如下所示:

public void run() {
    if (label1.InvokeRequired) //Is this method being called from a different thread
        this.Invoke(new MethodInvoker(()=> label1.Text = CONNECTING));
    else //it's cool, this is the original thread, procceed
        label1.Text = CONNECTING;
}


但是,如果您绝对确定该run()方法只会从线程中调用,请考虑甚至不检查是否InvokeRequired立即调用Invoke

更多信息: http: //msdn.microsoft.com/en-us/library/ms171728 (v=vs.80 ).aspx

停止正在进行的线程

  • Simples 是使用t1.Abort(); a 的方法Thread。这将抛出异常并迫使它停止在原来的位置。这对于不进行任何长时间处理的线程非常有用,因此停止它不会导致任何问题。

  • 如果你确实在你的线程中进行处理,这意味着你不能只是在中间停止它,那么我建议你使用一个布尔值来指示线程必须尽快取消。

private bool isCancelRequired = false;
public void run() {
     while(true) {
         //do long processing..
         if (isCancelRequired)
            break;
     }
} 
于 2013-07-25T23:43:00.180 回答