2012-07-19 38 views
1

我有一個不同於UI的線程運行的代碼,它必須創建一個控件(windows窗體)。但是,我沒有提及UI的任何控件(這樣,我可以使用myControl.Invoke(methodThatAddsControlToUI))。有沒有辦法做到這一點.net 緊湊框架?如果可能的話,我會對不使用其他控件引用的解決方案感興趣(跟蹤所有創建的表單,例如,將不是一個很好的解決方法,因爲我的代碼將位於庫中)。在完整的框架版本中,有Application.OpenForms屬性,但這不會在CF中退出。如何從其他線程(.net精簡框架)正確創建控件,而不參考其他控件?

編輯:

這樣做的主要目的是呼籲在UI線程的方法:

class Worker 
{ 
    public MyMethod() 
    { 
     // I need to call a method on the UI (this code doesn't run in the UI thread), 
     // but I don't have any field in this object holding an UI control 
     // value. So, I can't write myControlField.Invoke(...), 
     // but I still need to call a method on the UI thread 
    } 
} 

有什麼建議?

+0

我可能失去了一些東西,但你有什麼打算,如果你有沒有其他的控制來分配其與新的控制做至? – 2012-07-19 15:30:15

+0

我想用它來調用UI上的方法,有點像newControl.Invoke(myMethod) – 2012-07-19 15:32:46

+1

你可以給我們一些代碼示例嗎?我很難理解你想要做什麼!對於那個很抱歉。 – 2012-07-19 15:37:58

回答

2

從庫中確實沒有辦法保證你的線程上下文,所以你最安全的選擇是讓消耗提供調用者並把它留給他們,以確保它是在適當的上下文中創建的。事情是這樣的模式:

class Foo 
{ 
    private Control m_invoker; 

    public Foo() 
     : this(null) 
    { 
    } 

    public Foo(Control invoker) 
    { 
     if (invoker == null) 
     { 
      // assume we are created on the UI thread, 
      // if not bad things will ensue 
      m_invoker = new Control(); 
     } 
     else 
     { 
      m_invoker = invoker; 
     } 
    } 

    public void Bar() 
    { 
     m_invoker.Invoke(new Action(delegate 
     { 
      // do my UI-context stuff here 
     })); 
    } 
} 
1

我很抱歉,如果這不是一個真正的答案,但我認爲它可以幫助:

之所以有WinForms的這種方法 - 使用控制或Form引用來訪問一個Invoke方法,使您能夠在UI線程上運行代碼 - 是您必須在UI線程中運行代碼的唯一原因是,如果您要編寫/更改UI組件的狀態。

當然,如果你打算這樣做,你必須有一個UI組件的引用。所以你可以訪問它的Invoke方法。我想不出任何其他原因,你必須從組件中訪問UI線程,而不是修改視覺元素。

+0

是有意義的...意思是說,我會採取由ctacke建議的方法,並可能會重構我的應用程序解決這個問題...謝謝你的信息! – 2012-07-19 17:32:22

+0

我所知道的一個例子(因爲我必須在OpenNETCF IoC庫中處理它)是,如果一個庫需要能夠將事件引發給消費者,並且您想要這些事件,爲了玩得很好,在UI線程中引發,你需要這個能力。您不會影響UI元素,但您可以讓消費者接收事件,而無需執行自己的線程遷移。 – ctacke 2012-07-19 18:17:03

+0

@ctacke,我明白了,但我不確定它是否是最好的例子。如果這個庫對這個UI一無所知,那就不是一個UI庫,它不是將這些代碼編組到UI中的責任。如果沒有UI,該怎麼辦?也許你正在使用這個組件來構建一個服務。 – 2012-07-19 18:44:23

0

它必須被調用...但調用必須等待仍然主線程我的意思是你沒有得到這樣的錯誤,但這並不是簡單的並行工作,如果你想在同一時間去多個進程只是創建更多然後一個線程

Thread thread = new Thread(new delegate_method(method)); 
thread.start(); 
Thread thread2 = new Thread(new delegate_method(method2)); 
thread.start(); 

處理兩個過程同時

void method() 
{ 
//do something here -- working background Remember can not control any UI control from here 
finish_thread() 
} 

void method2() 
{ 
//do something here -- working background Remember can not control any UI control from here 
finish_thread() 
} 

void finish_thread() 
{ 
if(invoke.Required) 
{ 
//Here you have to call delegate method here with UI 
BeginInvoke(new delegate_method(finish_thread)); 
} 
else 
{ 
//Now you can control UI thread from here and also you finished background work 
//Do something working with UI thread 
textBox.Text = ""; 
} 
} 
0
//Declare this in class 
public delegate void delege(); 

//Write this lines when you want to background thread start 
    Thread thread = new Thread(new ThreadStart(() => { 
    //Do what you what with backgorund threading , can not use any interface comand here 
     BeginInvoke(new delege(() => { 
      //Do here any main thread thread job,this can do interface and control jobs without any error 
     })); 
    })); 
    thread.Start();