2016-06-14 3 views
0

타사 소프트웨어 용 플러그인을 만들고 있습니다. 플러그인은 리본 버튼과 Winform으로 구성됩니다. 리본에서 SW와 상호 작용하는 데 문제가 없습니다. 문제는 WinForm을 별도의 스레드에서 시작해야하므로 발생합니다. 왜? 그 아래의 UI에 대한 액세스를 차단하지 않고 최상단에 유지하기.크로스 스레드 업데이트 UI 문제

var thread = new System.Threading.Thread(() => { 
         var sc= new SetCategory(); 
         sc.ShowDialog(); 
}); 
thread.Start(); 

그런 다음, 그 "SetCategory"형태의 버튼에 의해 트리거, 내가 플러그인을 호스팅하는 소프트웨어에 액세스하고 값을 설정해야합니다

는이 같은 (이름 SetCategory) 폼을 실행하십시오. 이 같은 그것을 시도 :

SendOrPostCallback updateSegment = delegate(object state) 
{ 
    theApplication.theProprietaryControl = myValue 
}; 

System.Threading.SynchronizationContext.Current.Post(updateSegment, null); 

참고 :이 무관하다 나는 전체 응용 프로그램 제어 오두막을 포함하지 않았습니다. UI 스레드에서 Form을 시작한 후 나중에 닫아서 사용자가 응용 프로그램에서 계속 작업 할 수 있으면 모든 것이 올바르게 작동하므로 해당 동작 자체에는 아무런 문제가 없습니다.

나는 또한 MethodInvokerBeginInvoke를 사용하여 시도했지만 결과는 두 경우 모두에이기는하지만 동일 매우 이상한 일 :

동작이 수행> ==, 나는 나의 값이 설정되는 것을 볼 수 있습니다 - 아직

이 메소드/속성은 UI 스레드에서 호출해야합니다. 컨트롤의 InvokeRequired 속성을 테스트하고 을 수정하고 InvokeRequired가 true 일 때 을 직접 호출하는 대신 Invoke() 또는 BeginInvoke()를 호출하십시오.

내가 Continue으로 선택하면 계속 진행할 수 있으며 모든 것이 정상적으로 작동 한 것처럼 값이 설정됩니다. 할 수있는, 내가 작업이 올바른 스레드에서 실행되어 있는지 확인하기 위해 ThreadID을 사용할 수 없습니다

var uid = Thread.CurrentThread.ManagedThreadId; 
var thread = new System.Threading.Thread(() => { 
         var sc= new SetCategory(); 
         sc.Controls["lblUiThreadId"].Text = uid.ToString(); 
         sc.ShowDialog(); 
}); 
thread.Start(); 

아아 :

나는 버튼에서 양식을 실행하기 전에이 같은 UI 스레드의 ThreadId을 전달 시도 나는?

감사합니다.

+0

AFAIK 만드는 윈폼 비 UI 스레드의 컨트롤은 일반적으로 큰 "Nono"입니다. 따라서 앱 당 UI 스레드가 두 개 이상 있습니다. (https://support.microsoft.com/en-us/kb/943139) – user6144226

+1

한 가지를 이해하지 못합니다. 필요한 것이 있다면 _modal_ 대화 상자가없는 것입니다. 그렇다면 왜 안되나요? 'sc.ShowDialog()'대신에'sc.Show()'를 사용하고 _main_ 쓰레드에 살게 하시겠습니까? –

+0

@AdrianoRepetti 왜냐하면 나는 바보입니다. : -} 이전의 시도에서 나는 아래의 응용 프로그램을 클릭하면 양식이 다시 사라질 것으로 예상했습니다. 넌 모달 플러스 맨 위가 가장 잘 작동합니다. 귀찮게해서 미안해. – LocEngineer

답변

2

backgound 스레드에서 UI 스레드를 업데이트 할 수 없습니다. 모든 양식 상단에 양식을 표시하려면 TopMost = true;을 입력 한 다음 Show() 방법으로 전화하십시오.

+0

그냥 시도하지 않고 일을 맡을 때 일어나는 일입니다. 감사! – LocEngineer

0

모든 사용자 인터페이스 작업을 수행하는 스레드가 하나만 있어야합니다.

별도의 스레드가 대화 상자를 만들고 표시하도록하고 싶습니다. 왜냐하면 : "별도의 스레드에서 시작해야하는 이유는 무엇입니까? 아래 UI에 대한 액세스를 차단하지 않고 최상단에 유지해야합니다."

모달 및 모덜리스 대화 상자에 익숙합니까?

  • 모달 대화 상자가
  • 모델리스 대화 상자가 다른 사용자 활동

MSDN about modal and modeless dialog boxes

을 화면에 남아 언제든지 사용할 수 있지만 허용하는 프로그램을 계속하기 전에 응답하도록 사용자에게 요구

모덜리스 대화 상자가 필요합니다. ShowDialog 함수를 사용하여 폼을 표시합니다. ShowDialog는 폼을 모달 대화 상자로 표시하는 데 사용됩니다. 당신이 촬영하려는 경우 모덜리스 대화 상자를 사용 Form.Show()과 같다

반응 형 기본 폼

private SetCategory formSetCategory = null; 
private void Button1_clicked(object sender, ...) 
{ 
    if (this.formSetCategory == null) 
    { // form not showing yet, create + show 
     this.formSetCategory = new SetCategory(); 
     this.formSetCategory.ShowDialog(this); 
    } 
    // else: form already showing. Do nothing 
} 

지금이 형태와 formSetCategory 모두 반응하는 유지하면서 당신이 원하는 것을 할 것 다음 둘 다 동일한 UI 스레드를 사용합니다. 일반적으로 formSetCategory는 형태가 닫혀있는 경우, 당신은 확인, 통보하는 데 필요한, (닫기 또는 확인 버튼 같은) 자체를 닫 기능이 formSetCategory하는 명확한 참조한다 :

private SetCategory formSetCategory = null; 
private void Button1_clicked(object sender, ...) 
{ 
    if (this.formSetCategory == null) 
    { // form not showing yet 
     this.formSetCategory = new SetCategory(); 
     // subscribe to FormClosed event 
     this.formSetCategory.FormClose += this.OnSetCategoryFormClosed; 
     this.formSetCategory.ShowDialog(this); 
    } 
} 
private void OnSetCategoryFormClosed(object sender, FormClosedEventArgs e) 
{ // formSetCategory is closed.   
    this.formSetCategory.Dispose(); 
    this.formSetCategory = null; 
}