2012-06-16 25 views
1

直接返回一個對象我有一個這樣的方法:從方法使用線程池

public IOrganizationService GetConnection(bool multi) 
     { 
      if(!multi) 
      { 

      Parallel.For(0, 1, i => 
      { 
       dynamic _serviceobject= InitializeCRMService(); 

      }); 
      } 

      else 
      { 
       ThreadPool.QueueUserWorkItem 
       (
        new WaitCallback 
        (
         (_) => 
         { 
          dynamic _serviceobject= InitializeCRMService(); 

         } 
        ) 
       ); 
      } 

     } 

我想回報的_ serviceobject * 直接 *從內部method.Will returing它是兩次,即一次從if循環和一次從else循環解決我的問題。請注意我正在使用多線程使用池線程的概念。將_serviceobjects保持唯一的情況下,兩個線程並行運行。我不希望任何交互發生在我的線程之間。

+0

很抱歉,但你可以epxlain我,什麼是使用的意思' Parallel.For'和'dynamic'? –

回答

2

WaitCallback裏面的代碼將在線程池中執行,並且可能在GetConnection返回後執行(這是做異步操作的要點)。因此,由於它是另一個線程(使用另一個調用堆棧),並且在GetConnection已返回之後它可能會執行,因此您不能從WaitCallback內部返回GetConnection。如果你真的想這樣做,那麼你將不得不讓GetConnection等到WaitCallback已經完成執行。 ManualResetEvent可以訣竅:

public IOrganizationService GetConnection(bool multi) 
{ 
    var waitHandle = new ManualResetEvent(false); 
    dynamic result = null; 
    if(!multi) 
    { 
     Parallel.For(0, 1, i => 
     { 
      result = InitializeCRMService(); 
      waitHandle.Set(); 
     }); 
    } 
    else 
    { 
     ThreadPool.QueueUserWorkItem 
     (
      new WaitCallback 
      (
       (_) => 
       { 
        result = InitializeCRMService(); 
        waitHandle.Set(); 
       } 
      ) 
     ); 
    } 
    //We wait until the job is done... 
    waitHandle.WaitOne(); 
    return result as IOrganizationService; //Or use an adecuate casting 
} 

但是,這樣做首先違反了異步操作的要求。由於調用者線程必須等待,直到在另一個線程中完成工作,坐在那裏,什麼都不做......那麼,爲什麼不只是同步執行呢?總之:毫無意義。

問題是直接返回值是一個同步API。如果你想要異步操作,你需要一個非常規的API。如果你將有一個異步API,那麼你將不得不改變調用者的工作方式。

解決方案包括:

  1. 具有(如果可用的話也可以使用異步keywork)public property to access the reuslt(選項1)
  2. 有一個callback(選項2)
  3. resourcing to events
  4. 返回任務
  5. 返回IObservable(使用反應擴展,如果可用)

注:

  1. 有一個puplic屬性意味着你將需要應對呼叫者syncrhonization。
  2. 有一個回調,意味着一個奇怪的方式來調用該方法,並沒有明確的方式來等待。
  3. 使用事件可能會導致調用程序停留訂閱事件處理程序。
  4. 由於您正在使用線程池,因此返回一個任務看起來像是一種矯枉過正。
  5. 使用沒有Reactive Extension的IObservable容易出錯,並且與替代方法相比,更多的工作。

個人而言,我會去的回調選項:

public void GetConnection(bool multi, Action<IOrganizationService> callback) 
{ 
    if (ReferenceEquals(callback, null)) 
    { 
     throw new ArgumentNullException("callback"); 
    } 
    if(!multi) 
    { 
     Parallel.For(0, 1, i => 
     { 
      callback(InitializeCRMService() as IOrganizationService); 
      //Or instead of using "as", use an adecuate casting 
     }); 
    } 
    else 
    { 
     ThreadPool.QueueUserWorkItem 
     (
      new WaitCallback 
      (
       (_) => 
       { 
         callback(InitializeCRMService() as IOrganizationService); 
         //Or instead of using "as", use an adecuate casting 
       } 
      ) 
     ); 
    } 
} 

然後調用程序是這樣的:

GetConnection 
    (
     false, 
     (seriveObject) => 
     { 
      /* do something with seriveObject here */ 
     } 
    ); 
//Remember, even after GetConnection completed seriveObject may not be ready 
// That's because it is asyncrhonous: you want to say "hey Bob do this for me" 
// and you can go do something else 
// after a while Bob comes back an says: 
// "that thing you asked me to do? well here is the result". 
// We call that a callback, and the point is that you didn't have to wait for Bob 
// you just kept doing your stuff... 
//So... when is seriveObject ready? I don't know. 
//But when seriveObject is ready the callback will run and then you can use it 
+0

感謝一噸thearot ..你簡直是一個genious! –

1

你不能從WaitCallback處理程序中返回它,因爲代碼中沒有人返回它。這只是一個回調。 您可能想嘗試定義一個具有動態成員的自定義事件(從EventArgs派生)。

然後,您可以從您的工作人員入口點引發此事件,並將其與動態對象一起發送。

您可以綁定到需要的事件(即您想要使用動態對象的位置)。

EDIT(也顯示一些代碼):

在你有你的getConnection方法相同的類,還定義了一個事件:

internal event EventHandler<SomeEventArgs> OnWorkerFinished = (s, e) => {}; 

然後,在項目中的某處定義(接近這個類)中,SomeEventArgs類:

internal class SomeEventArgs : EventArgs 
{ 
    public dynamic WorkerResult { get; private set; } 

    public SomeEventArgs(dynamic workerResult) 
    { 
    WorkerResult = workerResult; 
    } 
} 

接下來,在工人:

new WaitCallback 
(
    (_) => 
    { 
     dynamic _serviceobject= InitializeCRMService(); 
    //Here raise the event 
    SomeEventArgs e = new SomeEventArgs(_serviceObject); 
    OnWorkerFinished(this, e); 
    } 
) 

我不知道你想在哪裏得到結果,但在那個地方,你應該綁定到這個類的OnWorkerFinished事件(你有GetConnectionMethod)。

+0

你可以請分享它的代碼?那麼我如何從Method返回對象呢? –

+0

我編輯了我的答案並添加了一些示例代碼。 –

+0

我從這樣的一個不同的類調用這個方法:IOrganizationService result = GetConnection(false); ..現在你的意思是說應該有一些在客戶端處理也請幫助.... –