2016-07-13 3 views
0

그래서이 응용 프로그램에는 몇 개의 버튼이있는 MainForm이 있습니다. 버튼은 MainForm UI로 작업하는 것을 포함하여 시간이 많이 걸리는 작업을 수행합니다. 몇 번이라도이 애플리케이션의 여러 인스턴스를 실행해야하기 때문에 MainFormHost를 만들기로 결심했습니다. 각 탭 아래에서 MainForm의 인스턴스를 만들고 탭 컨트롤을 가진 탭 컨트롤이있는 양식입니다. 그리고 지금까지 모든 것이 괜찮 았어. 문제는 MAinForm1의 버튼을 클릭하면 정상적으로 작동하지만 MainForm2의 버튼을 클릭하자 마자 MainForm1 버튼의 프로세스가 MainForm2 프로세스의 뒤에 대기하게됩니다.tabcontrol/queuing에서 여러 응용 프로그램 인스턴스 호스팅

MainForm GetMainFrom(TabPage tabPage) 
{ 
tabPage.Invoke(new Action(() => 
{ 
    mainForm = new MainForm(); 
    mainForm.TopLevel = false; 
    mainForm.FormBorderStyle = FormBorderStyle.None; 
    mainForm.Dock = DockStyle.Fill; 

    _mainForms.Add(mainForm); 
    tabPage.Controls.Add(mainForm); 
    mainForm.Show(); 

})); 
} 

그리고 다음 메서드를 호출 : 그들은이 일을 너무 많이 될 것입니다 때문에 UI 작업 할 때

var mainFormThread = new Thread(() => 
{ 
    mainForm = GetMainFrom(tabPage); 
}); 

mainFormThread.SetApartmentState(ApartmentState.STA); 
mainFormThread.Start(); 

내가 일을 호출하기 위해 MainForm 내부의 코드를 변경할 수 있지만, 나는 쉽게 한마디로

TIA

답변

0

, 당신은 단지 UI 컨트롤과 상호 작용할 수있는 하나의 '메인 스레드'를 할 수 있습니다 ... 각 버튼 클릭이 스레드/작업에서 호출 할 수 있도록하거나 할 수 있습니다. 이제까지. 기간. 이 문제를 해결할 방법이 없습니다 (표준 코드에서는 다른 프로세스에서 양식으로 그릴 수 있지만 그 내용은 다루지 않겠습니다.)

그래서 코드를 패턴을 설정합니다. 배경 작업을

  • 방법 -이 별도의 스레드 (들) UI를 업데이트
  • 방법에 수행 할 수는 -는 UI/메인 스레드

아이디어의 존재에서 수행해야합니다 간단한 배경 작업은 오랜 시간이 걸리고 UI를 업데이트하면 안됩니다.

MAIN UI THREAD에서 1 ~ 2 회의 장기 실행 액션이 실행 중이므로 'UI 차단'으로 인해 발생하는 동작이 원인입니다.

UI를 차단하면 실제로 Windows 메시지 펌프가 펌프를 사용할 수 없습니다. 따라서 창 크기를 조정하거나 양식의 컨트롤을 업데이트하는 모든 명령은 펌프의 메시지입니다. 그것은 주 스레드에서 실행되어야합니다. 데이터베이스에 연결하거나 파일을 다운로드하는 것과 같이 스레드에서 '작업'을 수행하면 펌프를 계속할 수 없으므로 '이 응용 프로그램이 응답하지 않습니다'라는 메시지가 표시됩니다.

그래서 파일이나 뭐든지 스레드에서 다운로드해야하며, 완료되면 UI 스레드로 전환하고 UI를 업데이트해야합니다. 텍스트 상자에서 말하기.

두 개의 스레드 (배경에서 주까지) 사이를 전환하는 방법은 begininvoke를 사용하는 것이며 'invoke required'를 사용하여 이것이 필요한지 알고 있습니다. MSDN about thread safe code and invoke required

+0

이 철저하게 설명 주셔서 감사합니다 :

// This method demonstrates a pattern for making thread-safe // calls on a Windows Forms control. // // If the calling thread is different from the thread that // created the TextBox control, this method creates a // SetTextCallback and calls itself asynchronously using the // Invoke method. // // If the calling thread is the same as the thread that created // the TextBox control, the Text property is set directly. private void SetText(string text) { \t // InvokeRequired required compares the thread ID of the \t // calling thread to the thread ID of the creating thread. \t // If these threads are different, it returns true. \t if (this.textBox1.InvokeRequired) \t { \t \t \t SetTextCallback d = new SetTextCallback(SetText); \t \t this.Invoke(d, new object[] { text }); \t } \t else \t { \t \t this.textBox1.Text = text; \t } }

이 좋은 기사이고 당신이 할 필요가 어디를 얻을 것이다 MSDN

에서

.그러나 나는 당신이 설명했던 것의 대부분을 알았지 만 나의 코드에 이런 종류의 변화를 가하지 않는 길/지름길이 있다면 제 질문이있었습니다. 예를 들어, 여러 UI 스레드를 만드는 것과 같은 것을 찾고 있거나 앱의 두 인스턴스를 실행하고 서로를 차단하지 않고 정상적으로 작동 할 때 작동하는 방식을 찾으십시오. 나는 많은 창을 열어두고 인스턴스를 탭 컨트롤로 관리하는 것을 선호하지 않습니다. – Alireza

+0

여러 프로세스 (기본적으로 실행중인 응용 프로그램의 여러 복사본) 외에도 아니요, 그렇지 않습니다. 미안하지만 근본적인 디자인 문제가 있습니다. '수정'하는 가장 간단한 방법은 작업 프레임 워크를 사용하는 것입니다. – adudley