2010-07-06 32 views
14

是否有任何方式在c#中將對象放入另一個線程?我發現的只是如何在另一個線程中實際執行某些方法。我真正想要做的是在新線程中創建一個對象,以便以後使用它提供的方法。如何將對象放入另一個線程?

希望你能幫助我, 日俄

+0

創建對象A靜態 – 2010-07-06 08:12:10

+14

捂臉@pranay :) – annakata 2010-07-06 08:26:37

+0

使用ParameterizedThreadStart將對象傳遞到您的線程。 – Serdar 2018-01-08 12:35:17

回答

-1

如果您在一個線程中運行的方法駐留在自定義類,你可以有這個類的成員來保存參數。

public class Foo 
{ 
    object parameter1; 
    object parameter2; 

    public void ThreadMethod() 
    { 
     ... 
    } 
} 
+0

我想知道你爲什麼被downvoted你的方法是乾淨的,容易理解的。主線程將可以通過線程啓動的對象訪問新創建的對象。同時,您的線程可以創建對象,而不會干擾其他線程。 – diadem 2010-07-14 14:30:50

+0

我想知道,要麼:) – 2010-07-14 14:56:57

+0

我認爲這個解決方案太幼稚了。對象不屬於線程ts是他們自己生活的實體。國際海事組織,如果需要像Foo這樣的班級,有設計錯誤。 – onof 2010-07-15 12:11:55

24

對象不屬於某個線程。如果你有一個對象的引用,你可以從許多線程訪問它。

這可能會導致對象的問題不能從許多線程訪問,如(幾乎所有)System.Windows.Forms類以及對COM對象的訪問。

如果您只想訪問同一個線程中的對象,請將對線程的引用存儲在對象(或包裝對象)中,然後通過該線程執行方法。

8

進程的所有線程共享相同的數據(忽略線程本地存儲),因此不需要在線程之間顯式遷移對象。

internal sealed class Foo 
{ 
    private Object bar = null; 

    private void CreateBarOnNewThread() 
    { 
     var thread = new Thread(this.CreateBar); 

     thread.Start(); 

     // Do other stuff while the new thread 
     // creates our bar. 
     Console.WriteLine("Doing crazy stuff."); 

     // Wait for the other thread to finish. 
     thread.Join(); 

     // Use this.bar here... 
    } 

    private void CreateBar() 
    { 
     // Creating a bar takes a long time. 
     Thread.Sleep(1000);    

     this.bar = new Object(); 
    } 
} 
2

的所有線程可以看到,所以如果線程必須你需要的對象的引用(通過方法通過在例如),則線程可以使用這些對象。這就是爲什麼在多線程時你必須非常小心地訪問對象,因爲兩個線程可能會嘗試同時更改對象。

有一個ThreadLocal<T>類在.NET中,你可以用它來限制變量特定線程:看http://msdn.microsoft.com/en-us/library/dd642243.aspxhttp://www.c-sharpcorner.com/UploadFile/ddoedens/UseThreadLocals11212005053901AM/UseThreadLocals.aspx

+3

「所有線程都可以看到堆棧」:否...每個線程都可以看到它自己的堆棧。但是,所有線程都可以看到堆。 – 2010-07-06 08:30:40

+0

我的錯誤。混淆堆和棧 - 初學者的錯誤! :( – 2010-07-06 08:39:31

1

使用ParameterizedThreadStart一個對象傳遞給你的線程。

0

「供以後使用它提供的方法」。

使用一個包含在新線程和其他數據和方法上執行的方法的類,可以從線程獲得對新線程中數據和方法的訪問權限。

但是...如果你從類中執行一個方法,你正在執行當前線程。

要在新線程上執行該方法,需要一些線程同步。

System.Windows.Forms.Control.BeginInvoke做到這一點,控制線程正在等待,直到請求到達。

WaitHandle class can help you。

12

似乎有一些混亂,線程是如何在這裏工作,所以這是一個底漆(很短,所以你應該提出進軍多線程編程之前找到更多的材料。)

對象和內存本質上是多線程的,因爲進程中的所有線程都可以根據自己的選擇訪問它們。

所以對象與線程沒有任何關係。

但是,代碼在一個線程中執行,並且它是您可能執行後的代碼執行的線程。

不幸的是,沒有辦法只是「放入一個對象到不同的線程」,你需要專門啓動一個線程並指定在該線程中執行的代碼。因此,該代碼使用的對象可以「說」屬於該線程,儘管這是您自己施加的人爲限制。

那麼有沒有辦法做到這一點:

SomeObject obj = new SomeObject(); 
obj.PutInThread(thatOtherThread); 
obj.Method(); // this now executes in that other thread 

其實,常見的陷阱很多新的多線程編程落入是,如果他們創建一個線程對象,並調用它的方法從另一個線程中,所有這些方法在創建該對象的線程中執行。這是不正確的,方法總是在調用它們的線程中執行。

那麼下面的內容也是不正確的:

Thread 1: 
    SomeObject obj = new SomeObject(); 

Thread 2: 
    obj.Method(); // executes in Thread 1 

,這裏將在線程2執行以獲得在原有的線程來執行方法的方式方法與原來的線程進行合作,「問它「來執行該方法。你如何做到這一點取決於具體情況,有很多種方法可以做到這一點。

所以總結一下你想要的:你想創建一個新的線程,並在該線程中執行代碼。

爲此,請參閱.NET的Thread類。

但要注意:多線程應用程序是極其難以得到正確的,我不會多線程功能,將程序添加,除非:

  1. 那就是擺脫它更多表現的唯一途徑
  2. 而且,你知道你在做什麼
0

對不起重複以前的一些工作,但OP說

我真正想要做的是在新線程中創建一個對象,以便以後使用它提供的方法。

讓我解釋,作爲:

什麼我其實想做的是有一個新的線程實例化一個對象,這樣我可以在以後使用該對象的方法。

如果我錯過了商標,請正確地爲我禱告。這裏的例子:

namespace silly 
{ 
    public static class Program 
    { 
     //declared volatile to make sure the object is in a consistent state 
     //between thread usages -- For thread safety. 
     public static volatile Object_w_Methods _method_provider = null; 
     static void Main(string[] args) 
     { 
      //right now, _method_provider is null. 
      System.Threading.Thread _creator_thread = new System.Threading.Thread(
       new System.Threading.ThreadStart(Create_Object)); 
      _creator_thread.Name = "Thread for creation of object"; 
      _creator_thread.Start(); 

      //here I can do other work while _method_provider is created. 
      System.Threading.Thread.Sleep(256); 

      _creator_thread.Join(); 

      //by now, the other thread has created the _method_provider 
      //so we can use his methods in this thread, and any other thread! 

      System.Console.WriteLine("I got the name!! It is: `" + 
       _method_provider.Get_Name(1) + "'"); 

      System.Console.WriteLine("Press any key to exit..."); 
      System.Console.ReadKey(true); 

     } 
     static void Create_Object() 
     { 
      System.Threading.Thread.Sleep(512); 
      _method_provider = new Object_w_Methods(); 
     } 
    } 
    public class Object_w_Methods 
    { 
     //Synchronize because it will probably be used by multiple threads, 
     //even though the current implementation is thread safe. 
     [System.Runtime.CompilerServices.MethodImpl( 
      System.Runtime.CompilerServices.MethodImplOptions.Synchronized)] 
     public string Get_Name(int id) 
     { 
      switch (id) 
      { 
       case 1: 
        return "one is the name"; 
       case 2: 
        return "two is the one you want"; 
       default: 
        return "supply the correct ID."; 
}}}} 
0

就像先前的答案詳細說明。爲了回到這個問題,所有線程都共享對象和內存空間。所以他們總是共享的,但我假設你想要安全地做到這一點,並處理由另一個線程創建的結果。

首先嚐試一種可信的C#模式。 Async Patterns 有設置的模式可以使用,它們可以在線程之間傳輸基本消息和數據。 通常在計算結果後,一個威脅就完成了!

生命威脅:在異步和共享生命威脅數據時,沒有什麼是傻瓜證明。 所以基本上儘可能簡單,如果你需要走這條路線,並嘗試遵循已知的模式。

所以,現在我只是想闡述爲什麼一些已知patters有一定的結構:

EventArgs的:在您傳遞之前,創建對象的deepcopy的。 (這不是萬無一失的,因爲某些引用可能仍然是共享的。) 通過基本類型(如int floats等)傳遞結果,這些可以在構造函數上創建並且不可變。

原子關鍵詞一個這些類型,或創建監視器等。堅持一個線程讀取其他寫入。

假設你有複雜的數據,你喜歡在兩個線程上同時使用一種完全不同的方式來解決這個問題,我還沒有測試過: 你可以在數據庫中存儲結果並讓其他可執行文件讀取它。 (鎖行發生在行級,但你可以再試一次或更改SQL代碼,至少你會得到報告的死鎖,可以用優秀的設計來解決,而不僅僅是掛起軟件!!)我只會這樣做,如果它實際上由於其他原因,將數據存儲在數據庫中。

另一個有用的方法是編程F#。有些對象和所有類型默認情況下都是不可變的。所以你想要共享的對象應該有一個構造器,並且沒有方法允許對象被修改或者基本類型被增加。 所以你創建它們,然後他們不會改變!所以他們在那之後是不可變的。 使鎖定和並行處理變得容易得多。不要在C#類中爲此瘋狂,因爲其他人可能會遵循這個「約定」,而像List這樣的大多數東西並沒有被設計成在C#中不可變(readonly與constant不一樣,const是非常有限的)。 Immutable versus readonly

+0

有一些奇怪的威脅這個答案... – Nyerguds 2017-11-23 11:56:57

相關問題