繁体   English   中英

无法在backgroundworker(C#Winform)中为文本框分配值

[英]Can not assign value for textbox in backgroundworker (c# winform)

public class Form1
{
    public delegate void SetStatus (string status);
    public event SetStatus SetStatusHandler;

    public BackgroundWorker bw = new BackgroundWorker();

    public Form1()
    {
        tbxResult.Text = "Assign text Ok";

        SetStatusHandler += delegate(string status)
            {
                tbxResult.Text = status; // can not assign
            };

        bw.DoWork += backgroundWorker_DoWork;
        bw.RunWorkerAsync();

    }

    void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        var status = "assign some value";
        SetStatusHandler(status);
    }
}

首先,我尝试在BackgroundWorker内的主线程上设置文本框tbxResult的值,但是它不起作用,然后我使用委托从主线程分配文本框值,但它也无法正常工作...

请帮我...怎么了?

希望逻辑有道理。 但是委托声明是错误的,您必须在SetStatus声明中指定返回类型以使其起作用。 因此,如下更改声明:

public delegate void SetStatus (string status);

仍然会收到异常(注释中提到的IllegalCrossThreadCallExceptionRené Vogt )意味着您可以定义事件处理程序,如下所示:

SetStatusHandler += delegate(string status)
 {
     tbxResult.Invoke(new MethodInvoker(delegate
     {
         tbxResult.Text = status;
     }));

 };

我们需要使用主UI线程再次调用该方法。 看看更多信息C#中MethodInvoker的用法

tbxResult.Invoke((MethodInvoker) delegate
    {
        tbxResult.Text = status;
    });

总的来说,我认为BackgroundWorker已过时,最好使用async/await模式。 但这将是一个过于宽泛的答案。

因此,直接的答案是:您的事件处理程序不在UI线程上执行,但仍在后台工作线程上执行。 从后台工作程序重新调用ui线程上的操作的通常方法是使用它的ReportProgress方法:

public Form1()
{
    tbxResult.Text = "Assign text Ok";
    bw.DoWork += backgroundWorker_DoWork;
    bw.WorkerReportsProgress = true;
    bw.ProgressChanged += (sender, e) => tbxResult.Text = (string)e.UserState;
    bw.RunWorkerAsync();
}

void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    var status = "assign some value";
    bw.ReportProgress(0, status);
}

ReportProgress()UI线程上调用ProgressChanged事件,因此您可以将文本分配给文本框。 记住将WorkerReportsProgress设置为true

像这样使用InvokeRequred(或与您的代表一起使用):

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        if (textBox1.InvokeRequired)
        {
            textBox1.Invoke((MethodInvoker) delegate { textBox1.Text = @"AAAAAA"; });
        }
        else
        {
            textBox1.Text = @"AAAAAA";
        }
    }

ps:另请参阅Invoke调用中的匿名方法

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM