2009-07-14 2 views
14

간단한 상태 업데이트와 경우에 따라 진행률 표시 줄에 대한 내 응용 프로그램의 하단에 StatusStrip을 사용하는 경향이 있습니다.ToolStripStatusLabel에 대한 크로스 스레드 호출은 어떻게합니까?

그러나 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

@Maslow : Control.Invoke 주위에 당신의 논리에주의하십시오.문서에있는 규칙은주의 깊게 읽지 않으면 미묘하고 오류가 발생하기 쉽습니다. Invoke를보다 적절하게 사용하려면 링크에있는 코드를 확인하십시오. 예를 들어, 구현시 'ToolStrip'핸들이 삭제되지 않았으며 'ToolStrip' 핸들이 생성되었는지 확인할 수 없습니다. –

+0

핸들이 아직 생성되지 않은 것 외에, 어쨌든 예외가 발생하면 예외를 throw하는 것 외에는 아무 것도하지 않는 것처럼 보입니다. 맞습니까? 핸들이 아직 생성되지 않은 경우에는 아무 일도 없었던 것처럼 가장하고 예외를 throw하지 않는 것이 유용하지는 않습니다. – Maslow

답변

27

이 좋은 질문입니다!

ToolStripStatusLabel은 컨트롤을 상속하지 않지만 ToolStrip은 포함합니다! ToolStrip의 Invoke가 포함 된 것을 사용하여 ToolStripStatusLabel에 대해 전화하십시오.

이것은 각각 WPF가 구성 요소 비트의 모두의 그림을 관리하는 것과 같은 방식으로 구성 요소 비트의 드로잉을 수동으로 처리하기 때문입니다. 이것은 모든 Control에 연결된 HANDLE이 있고 시스템에는 제외 할 수있는 숫자가 있습니다 (예 :

). another question에 사이드 바는, 예를 들어. 내가 더 최근의 이해를 반영하기 위해 텍스트를 업데이트해야합니다.)

+1

그래, Forms Invoke 메서드는 같은 스레드에서 만들어 졌으므로 사용할 수도 있습니다. 하지만 더 논리적 인 Greg D의 솔루션을 사용할 것입니다. –

+0

@sindre, 반드시 그런 것은 아니지만 아마도 ... ToolStripStatusLabels가 StatusStrip과 동일한 스레드에서 필요에 따라 생성되는 반면 –

2

또한, 일반적으로 당신이하지 가 동일한 컨트롤에 InvokeRequired 및 BeginInvoke를 사용해야합니까 당신을 조작중인 컨트롤이 동일한 스레드에서 생성되었음을 보증 할 수있는 한 코드에서 조작하고 있습니다 (예 : 폼의 initializat 이온 루틴)을 InvokeRequired/BeginInvoke를 호출하는 UI 요소로 사용합니다.

+0

흥미로운 세부 정보 – Maslow

0

delegate 키워드와 Control.Invoke() 메서드를 사용하여이 작업을 수행 할 수 있습니다. 이 예는 thread safe . 텍스트.ForeColor을 조정하는 방법을 보여줍니다. 이 같은이 방법의 스레드 안전 호출 할 수있는 스레드 컨텍스트 내부

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

을의 StatusStrip 항목을 통과하면서 통과 StatusStrip도 매개 변수를 따라 가며 StatusStrip.BeginInvoke 또는 Invoke 메서드로 사용하고 Status strip 항목을 그 안에 배치합니다.

아래 코드는 다른 작업/스레드뿐만 아니라 다른 클래스에서도 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 Screenshot