我倾向于在大多数应用程序的底部使用StatusStrip进行简单的状态更新,偶尔也会使用进度条。
但是,看起来ToolStripStatusLabels不会从控件继承,因此它们没有.Invoke或.InvokeRequired。那么我如何线程安全地调用来改变它的文本属性呢?
后代和其他搜索的代码答案:
Action<string> test=(text) =>
{
if (this._statusStrip.InvokeRequired) this._statusStrip.Invoke(
new MethodInvoker(() => this._lblStatus.Text = text));
else this._lblStatus.Text = text;
};
或
private void TestInvoker(string text)
{
if (this._statusStrip.InvokeRequired)
this._statusStrip.Invoke(
new MethodInvoker(() => this._lblStatus.Text = text));
else this._lblStatus.Text = text;
}
答案 0 :(得分:28)
这是一个很好的问题!
虽然ToolStripStatusLabel
不从控件继承,但包含ToolStrip
的确是如此!使用包含ToolStrip
的Invoke来对ToolStripStatusLabel
进行调用。
这是因为ToolStrip手动处理其组件位的绘制,这与WPF管理所有其组件位的绘制的方式非常相似,而不为每个位生成单独的句柄。这很有用,因为很容易忘记每个Control
都有一个关联的HANDLE
,并且系统只有有限数量的那些要出来,例如..
(我之前也遇到过这个问题。例如,我在another question的侧边栏中提到过它。我应该更新该文字以反映我最近的理解。)
答案 1 :(得分:2)
另外,一般情况下,你没有 拥有 来在代码中操作的完全相同的控件上使用InvokeRequired和BeginInvoke,只要你能保证您正在操作的控件是在同一个线程上创建的(例如,在表单的初始化例程中),作为您调用InvokeRequired / BeginInvoke的UI元素。
答案 2 :(得分:1)
您可以使用 delegate
关键字和Control.Invoke()方法来完成此操作。此示例显示了如何管理线程安全 .Text 和 .ForeColor 调整。
private delegate void SetToolStripDelegate(string text,Color color);&#xA;&#xA; private void SetToolStrip(string text,Color color)&#xA; {&#xA; statusBar.Text = text;&#xA; statusBar.ForeColor = color;&#xA;}&#xA;
&#xA;&#xA; 在线程上下文中,您可以对此方法进行线程安全调用,如这个:
&#xA;&#xA;&#xA;&#xA;
{//线程开始...&#xA;&#xA ; //线程内的某个地方&#xA;调用(新的SetToolStripDelegate(SetToolStrip),“已连接。”,Color.Green);&#xA;&#xA;} //线程结束...&#xA;
&#xA;
答案 3 :(得分:0)
简单来说,在传递StatusStrip项时,在参数中传递StatusStrip并使用StatusStrip.BeginInvoke或Invoke方法并将状态条项放在其中。
下面的代码应该可以帮助您不仅从其他任务/线程调用和更新StatusStrip,还可以从其他类调用和更新。
//Coded by Chandraprakash [2017-07-18]
//frozenprakash.com
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace UIUpdateFromOtherClass
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
FN_Execute();
}
async void FN_Execute()
{
Second s = new Second();
await Task.Run(() => s.Execute(lbl1,
pb1,
ss1,
ss1Lbl1,
ss1Pb1)
);
MessageBox.Show("End");
}
}
public class Second
{
public void Execute(Label lbl1,
ProgressBar pb1,
StatusStrip ss1,
ToolStripLabel tsLbl1,
ToolStripProgressBar tsPb1)
{
lbl1.BeginInvoke(new Action(() =>
lbl1.Text = "Second"
));
pb1.BeginInvoke(new Action(() =>
{
pb1.Style = ProgressBarStyle.Marquee;
pb1.MarqueeAnimationSpeed = 10;
}));
ss1.BeginInvoke(new Action(() =>
{
tsLbl1.Text = "Second";
tsPb1.Style = ProgressBarStyle.Marquee;
tsPb1.MarqueeAnimationSpeed = 10;
}));
Thread.Sleep(3000);
}
}
}
答案 4 :(得分:0)
您是否尝试过 GetCurrentParent()?这对我有用!
private delegate void SetToolStripStatusLabelTextDelegate(ToolStripStatusLabel label, string text);
public static void SetToolStripStatusLabelText(ToolStripStatusLabel label, string text)
{
if (label.GetCurrentParent().InvokeRequired)
{
label.GetCurrentParent().Invoke(new SetToolStripStatusLabelTextDelegate(SetToolStripStatusLabelText), label, text);
}
else
{
label.Text = text;
label.Invalidate();
}
}