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:/
以下是我认为类中需要进行后台工作的重要部分:
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异常。我相信这将解决您的问题,因为听起来您的其余代码是正确的?