Winforms:从另一个类更新Form上的标签

本文关键字:Form 标签 更新 另一个 Winforms | 更新日期: 2023-09-27 18:28:43

我有一个项目,需要从另一个classes方法内部更新标签文本。值得注意的是,这个方法是从后台工作线程调用的。

我已经尝试在Workers ReportProgress()中将文本作为UserState Obj进行更新;方法,然后在主窗体上触发workers progress changed事件时更新标签。这很有效,但显然只在引发progress changed事件时才更新标签文本。

我有不断加载/删除代理的代码,我需要一个标签来显示这一点(而不是只在bg工作进程更改事件触发时更新)。希望有人能帮忙。

感谢

编辑*以下是一些让问题更容易理解的代码:-

  public string Request(string action)
    {
        if (string.IsNullOrWhiteSpace(action))
        {
            return "";
        }
        HttpWebRequest req;
        string response = string.Empty;
        while (response.Equals(string.Empty) && proxy != null)
        {
            try
            {
                req = (HttpWebRequest)WebRequest.Create(action);
                req.Proxy = proxy;
                response = new StreamReader(req.GetResponse().GetResponseStream()).ReadToEnd();
            }
            catch (Exception ex)
            {
                RemoveProxy(proxy);
                MessageBox.Show("Proxy Removed: " + proxy.Address.ToString());
                proxy = GenNewProx();
                MessageBox.Show("New proxy" + proxy.Address.ToString());
            }
        }
        return response;
    }

^^^-在我需要设置标签文本的地方,目前使用Msgboxs,但更新主表单上的标签显然更可取

   foreach (string url in URLs)
        {
            result.URL = url;
            result.Shares = grabber.GetFacebookShares(url);
            result.Tweets = grabber.GetTweetCount(url);
            result.PlusOnes = grabber.GetPlusOnes(url);
            bgWorker.ReportProgress((outputGridView.Rows.Count * 100) / importGridView.Rows.Count, result);
        }

^^^-在bg内部,工人在主窗体上执行do_work方法。

第二次编辑*

我对事件有点陌生,但每次我切换代理并用新的Proxy/msg.we传递字符串参数,然后在主窗体中订阅该事件,然后在该事件触发时在主窗体上设置标签text=字符串参数时,我是否可以不触发自定义事件,比如Proxy_Changed?不过,我可能说的是jibberish tbh:/

Winforms:从另一个类更新Form上的标签

以下是我认为类中需要进行后台工作的重要部分:

public class Grabber
{
    public event EventHandler<MyArgs> NotifyParentUI;
    // other code.....
    public string Request(string action)
    {
        if (string.IsNullOrWhiteSpace(action))
        {
            return "";
        }
        HttpWebRequest req;
        string response = string.Empty;
        while (response.Equals(string.Empty) && proxy != null)
        {
            try
            {
                req = (HttpWebRequest)WebRequest.Create(action);
                req.Proxy = proxy;
                response = new StreamReader(req.GetResponse().GetResponseStream()).ReadToEnd();
            }
            catch (Exception ex)
            {
                RemoveProxy(proxy);
                NotifyParentUI(this, new MyArgs() 
                   { Message = string.Format("Proxy Removed: {0}", proxy.Address.ToString()) });
                proxy = GenNewProx();
                NotifyParentUI(this, new MyArgs() 
                   { Message = string.Format("New Proxy: {0}", proxy.Address.ToString()) });
            }
        }
        return response;
    } 
}

在你的主表单中,你有一种方法来更新你的标签,这是线程安全的:

public void UpdateMyLabel(object sender, MyArgs ea)
{
    this.Invoke(new MethodInvoker(
        delegate()
        {
            labelControl1.Text = ea.Message;
        }
        ));
}

同样在主表单中,您必须创建一个"抓取器"的实例:

Grabber grabber = new Grabber();
grabber.NotifyParentUI += UpdateMyLabel;

您应该有一个在自己的线程上运行的方法:

public void ThreadProc()
{
    // other code before this....
    foreach (string url in URLs)
    {
       result.URL = url;
       result.Shares = grabber.GetFacebookShares(url);
       Thread.Sleep(0); // may want to take the Sleeps out
       result.Tweets = grabber.GetTweetCount(url);
       Thread.Sleep(0);
       result.PlusOnes = grabber.GetPlusOnes(url);
       Thread.Sleep(0);
    }
}

以下是如何在主表单的部分启动线程:

Thread t = new Thread(new ThreadStart(ThreadProc));
t.Start();

附带说明一下,如果您需要将数据传递给Thread,请查看此处:向线程传递数据和从线程检索数据

使用Invoke方法在UI线程上运行匿名函数来更新标签。例如:

        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += (sender, args) =>
                        {
                            for (int i = 0; i < 10000; ++i)
                            {
                                DoSomeWorkInBackground();
                                // Update the label in UI thread
                                MyOtherFormInstance.Invoke((MethodInvoker)delegate()
                                                                            {
                                                                                MyOtherFormInstance.SetLabelText(i);
                                                                            });
                                DoSomOtherWorkInBackground();
                            }
                        };

在您的表格中:

    public void SetLabelText(int i)
    {
        myLabel.Text = i.ToString();
        // not sure that this needed, but try:
        myLabel.Invalidate();
    }

从您的问题和随后的评论到其他答案,听起来您正在WinForms项目中运行代码,如果我错了,请纠正我?在winform中,主程序线程通常是静态的(static void main()),因此您必须使EventHandler为静态,以避免null异常。我相信这将解决您的问题,因为听起来您的其余代码是正确的?