Как сделать перекрестные вызовы для ToolStripStatusLabel? - PullRequest
15 голосов
/ 15 июля 2009

Я склонен использовать 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;
    }

Ответы [ 4 ]

29 голосов
/ 15 июля 2009

Это хороший вопрос!

Пока ToolStripStatusLabel не наследует от контроля, содержащее ToolStrip делает! Используйте содержащий ToolStrip Invoke, чтобы совершать вызовы против ToolStripStatusLabel.

Это потому, что ToolStrip вручную обрабатывает отрисовку своих битов компонента, почти так же, как WPF управляет отрисовкой всех его битов компонента, не генерируя отдельный дескриптор для каждого. Это полезно, потому что легко забыть, что у каждого Control есть связанный HANDLE, а система имеет только конечное число из них, например,

(Я сталкивался с этим и раньше. Я упомянул об этом на боковой панели , например, еще один вопрос . Я должен обновить этот текст, чтобы отразить мое более недавнее понимание.)

2 голосов
/ 15 июля 2009

Кроме того, как правило, у вас нет для использования InvokeRequired и BeginInvoke для того же элемента управления, которым вы манипулируете в коде, при условии, что вы можете гарантировать, что элемент управления, которым вы управляете, был создан в том же потоке (например, в подпрограмме инициализации форм), что и элемент пользовательского интерфейса, для которого вы вызываете InvokeRequired / BeginInvoke.

1 голос
/ 20 июня 2016

Это можно сделать с помощью ключевого слова delegate и метода Control.Invoke (). В этом примере показано, как управлять потокобезопасными .Text и .ForeColor ajustment.

private delegate void SetToolStripDelegate(string text, Color color);

private void SetToolStrip(string text, Color color)
{
    statusBar.Text = text;
    statusBar.ForeColor = color;
}

Внутри контекста потока вы можете сделать потокобезопасный вызов этого метода следующим образом:

{ // thread begin...

    // somewhere inside the thread
    Invoke(new SetToolStripDelegate(SetToolStrip), "Connected.", Color.Green);

} // thread end...
0 голосов
/ 18 июля 2017

Проще говоря, передавая элементы 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);
    }
}

}

Снимок экрана Windows Forms

...