none
關於thread的委派問題 RRS feed

  • 問題

  •  

    最近看到關於thread的一些用法,自已試了一下,出現了一些疑問,想請問一下各位。

    class text

    {

    arraylist myarraylist=new arraylist( );

    public void copy( arraylist ar1)

    {

     ar1=this.myarraylist;

    }

     

    public void copy_thread(arraylist ar2)

    {

    threadstart mythreadstart = new threadstart ( copy( ar2 ) );

    thread mythread = new thread( mythreadstart );

    mythread.start( );

    }

    }

    上面的程式所理當然是無法執行的,只是大概的說明一下程式的功能。就我所知,使用thread是不能夠有輸入和輸出的,因此如果程式有"同步"的需求,並且所提供的方法需要能夠有輸入或輸出的話,那是否就無法用thread呢? 或是說有其他的方法可以使用呢?  感激不盡。

     
    2008年5月11日 下午 06:40

解答

  • 我說了一堆,你的程式碼沒做到半點......

    Code Snippet

        class test
        {
            public int value;
            List<test> tests = new List<test>();

     

            private void print(object o)
            {
                tests[(int)o].value = this.value;
            }


            public void Amplify(ref test t1, ref test t2)
            {
                 tests.Clear();
                 tests.Add(t1);
                 tests.Add(t2);
                 ThreadPool.QueueUserWorkItem(new WaitCallback(print), 0);
                 ThreadPool.QueueUserWorkItem(new WaitCallback(print), 1);
            }
        }

     

     

    2008年5月16日 下午 08:01

所有回覆

  • 有一篇文章是關於多執行緒的,我覺得還不錯,或許對你有幫助.

    http://blog.darkthread.net/blogs/darkthreadtw/archive/2008/03/26/better-winform-ui.aspx

     

    2008年5月12日 上午 03:22
  •  

    實在是太慘了....網頁居然打不開

    請問還有什麼其他網站可以參考的嗎???

    2008年5月12日 下午 04:26
  • 試試看
    http://blog2.darkthread.net/blogs/darkthreadtw/archive/2008/03/26/better-winform-ui.aspx

    另參考:
    http://www.albahari.com/threading/


    2008年5月12日 下午 04:56
  • 如果是只是控制項內容的變更:

    [VB2005]工作緒變更畫面控制項的值

     

    更多的內容可搜尋既有討論:

    http://forums.microsoft.com/MSDN-CHT/Search/Search.aspx?words=BackgroundWorker&localechoice=31748&SiteID=14&searchscope=allforums

     

    關於執行緒的相互等待,線上手冊有一系列的主題可以參考,建議先看一下。

    逐步解說:使用 Visual C# 撰寫簡單的多執行緒元件

    ms-help://MS.MSDNQTR.v80.cht/MS.MSDN.v80/MS.VisualStudio.v80.cht/dv_fxmclicc/html/7bc03b7b-d680-499b-8179-5f414b2d650c.htm

     

    逐步解說:使用 Visual C# 撰寫簡單的多執行緒元件

    ms-help://MS.MSDNQTR.v80.cht/MS.MSDN.v80/MS.VisualStudio.v80.cht/dv_fxmclicc/html/b9f04330-2d43-4372-b63e-cf2f5488d396.htm

     

    事件架構非同步模式概觀

    ms-help://MS.MSDNQTR.v80.cht/MS.MSDN.v80/MS.VisualStudio.v80.cht/dv_fxadvance/html/792aa8da-918b-458e-b154-9836b97735f3.htm

     

    使用事件架構非同步模式設計多執行緒程式

    ms-help://MS.MSDNQTR.v80.cht/MS.MSDN.v80/MS.VisualStudio.v80.cht/dv_fxadvance/html/958d6617-5e70-4b36-b5db-63c16dc35e43.htm

     

    ... 還有很多,用多執行緒為關鍵字就一堆~

    2008年5月13日 上午 10:18
  •  

     

    感謝以上各位先進的提示,我仔細的看了一下,發現使用threadpool似乎可以將參數丟到方法中,下面我有測試過了,是可以執行的,可是方法似乎只能多載+1的樣子....,下面是程式碼:

     class DNA

    {

            ArrayList Myarraylist = new ArrayList( );

            private void print(object in1)
            {
                ArrayList newarray=(ArrayList)in1;
                for (int i = 0; i < newarray.Count; i++)
                {
                    this.Myarraylist.Add(newarrayIdea);
                }
            }

            public void Amplify(ArrayList ar1)
            {
                ArrayList myarray = new ArrayList();
                for (int i = 0; i < ar1.Count; i++)
                {
                    myarray.Add(ar1Idea);
                }
                    ThreadPool.QueueUserWorkItem(new WaitCallback(print), myarray);
            }

    }

    static void Main(string[] args)
            {
                DNA mydna = new DNA();

                ArrayList ar2 = new ArrayList();
                for (int i = 0; i < 5; i++)
                {
                    ar2.Add(i * 5);
                }
                mydna.Amplify(ar2);
               
                Console.Read();
            }

    在上述的程式碼,我利用了ar2 來改變mydna的arraylist內的元素,可是如果我如果把print( )這個方法的參數設計成2個,就會出現沒有符合WaitCallback的委派了,雖然這也許能利用改變思考邏輯的方式來改善,但我想請教一下,難道這就是thread 的極限了嗎????還是說關於我的疑問,有更適合的方法呢? ps.關於backgroundword的部份我還沒看

    2008年5月13日 下午 03:09
  • 要多個參數就把所有參數通通塞到一個List<object>中傳過去,再自己取出來。

    如ThreadPool.QueueUserWorkItem(new WaitCallback(print), new List<object>() {myarray1, myarray2, myarray3} );

    或是寫個的class紀錄每個參數,然後傳一個該class的object過去。

    2008年5月14日 上午 04:52
  •  Eric Tsai 寫信:

    要多個參數就把所有參數通通塞到一個List<object>中傳過去,再自己取出來。

    如ThreadPool.QueueUserWorkItem(new WaitCallback(print), new List<object>() {myarray1, myarray2, myarray3} );

    或是寫個的class紀錄每個參數,然後傳一個該class的object過去。

     

    哈哈,Eric兄真是點醒了我,原來把它們包含一個物件就可以處理了。但突然又想到了,如果今天是要更改輸入的物件,也就是說

    private void print( object input)
            {
                input = this.array;  //被修改的是輸入的參數,而不是利用輸入的參數來修改
            }

     

     

    ThreadPool.QueueUserWorkItem(new WaitCallback(print), new List<object>() {myarray} );

     

     

    如果是遇到上述的需求時,我試著利用ref的方式來取值,但卻又不符合委派的定義了, 實在很困擾呀....。不知道有什麼方法嗎??

    2008年5月14日 下午 02:59
  • 那就用全域變數吧...有很多個的話一樣可以用List或Dictionary之類的放,然後傳個index或key進去。

    2008年5月14日 下午 03:15
  •  

    感謝Eric兄的幫助,但那樣似乎解決不了我的需求,我把我的目的說明一下,好讓大家明白。其實我是打算實作生物計算領域裡面的功能,而這些功能(方法)都能夠平行處理,讓打算使用生物計算的人能夠簡單的實作出來,下面是使用的方式:

    void main
    {
      parallelarray mypa1= new parallelarray(1);
      parallelarray mypa2= new parallelarray(2);
      parallelarray mypa3= new parallelarray(3);
      mypa1.copy(mypa2,mypa3);
      //程式執行完後,mypa2.value跟mypa3.value的會等於mypa1.value(也就是1)
    }

    class parallelarray
    {
      public int value;
     
      public parallelarray(int val)
      {
        this.value=val; // 初始化物件
      }
      static void copy(object ar)
      {
        ar=this.value //將輸入的參數設為物件本身的值
      }
      public void amplify(parallelarray pa1,parallelarray pa2)
      {
        ThreadPool.QueueUserWorkItem(new WaitCallback(print), pa1);
        ThreadPool.QueueUserWorkItem(new WaitCallback(print), pa2);
      }

     

    上述就是我的目的,由於.net所嚴格限制了thread 的委派,使我不得不換個方式來實作了,不知道各位前輩有沒有什麼好方法呢? 不知道用begininvoke方法能不能達成呀??

    2008年5月15日 下午 04:41
  • 你的copy看起來跟ThreadPool根本沒關係,實在看不太懂你的意圖......

    2008年5月15日 下午 06:28
  •  

    抱歉,是我的疏忽,程式應改成下面這樣:

    class parallelarray
    {
      public int value;
     
      public parallelarray(int val)
      {
        this.value=val; // 初始化物件
      }
      static void copy(object ar)
      {
        ar=this.value //將輸入的參數設為物件本身的值
      }
      public void amplify(parallelarray pa1,parallelarray pa2)
      {
        ThreadPool.QueueUserWorkItem(new WaitCallback(copy), pa1);
        ThreadPool.QueueUserWorkItem(new WaitCallback(copy), pa2);
      }

     使用threadpool將ampilfy的輸入參數也當然copy的輸入參數,並且更改這個輸入參數的值是我的野望。
    2008年5月15日 下午 06:34
  • 假設你的mypa1.copy其實是mypa1.amplify,這樣還是看不出為什麼不直接在amplify裡面做pa1.value=this.value、pa2.value=this.value。還有static function不能存取非static member。

    2008年5月15日 下午 06:37
  •  

    其實之所以不直接把值丟進去,還特別使用thread的這種方式,只是希望程式有"同步執行"的意味在,當然,功能上並非只是單純的復制,其實還有其他的功能的,只是我是用這種方式來舉。另外,我又打錯了,不是static,而是private.....實在非常抱歉....Orz
    2008年5月15日 下午 07:32
  • parallelarray裡面加兩個變數,amplify時將值分別設為pa1, pa2,main裡面改用by ref的方式傳給amplify,這樣不就可以在copy裡面存取到mypa2, mypa3了嗎?而copy的參數用途則是用來讓你分辨該抓哪個變數來用。就跟我前面回的一樣啊。

    2008年5月15日 下午 07:56
  •  

    請問Eric兄,你是指這個意思嗎?

     static void Main(string[] args)
            {
                test test1 = new test();
                test test2 = new test();

      test1.value=100;

      test1.Amplify(ref  test2.value);

    }

      class test
        {

            public int value;

            private void print( object input)
            {
                input = this.value;    
            }
            public void Amplify(ref int in1)
            {

                 ThreadPool.QueueUserWorkItem(new WaitCallback(print), in1);
            }

        }

     

    不知道我有沒有誤會Eric兄的意思,因為如果我如果使用print( ref object input)的話,會出現委派不符合定義的問題出現 。而且若是依照上面的方式,回到主程式,並沒有修改test2.value。方便的話,能不能麻煩Eric兄示範一下如何撰寫才能得到正確的結果呢?

    2008年5月16日 上午 07:57
  • 我說了一堆,你的程式碼沒做到半點......

    Code Snippet

        class test
        {
            public int value;
            List<test> tests = new List<test>();

     

            private void print(object o)
            {
                tests[(int)o].value = this.value;
            }


            public void Amplify(ref test t1, ref test t2)
            {
                 tests.Clear();
                 tests.Add(t1);
                 tests.Add(t2);
                 ThreadPool.QueueUserWorkItem(new WaitCallback(print), 0);
                 ThreadPool.QueueUserWorkItem(new WaitCallback(print), 1);
            }
        }

     

     

    2008年5月16日 下午 08:01
  • 真是太感謝Eric兄了,原來先前所指的是這個意思,我完全沒有想到要這樣來處理....實在太佩服了....Orz 。如此一來就解決了我的問題,真想送Eric兄一個。謝謝啦 ~~~~~

    2008年5月17日 下午 02:15