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,那麼你將不得不改變調用者的工作方式。
解決方案包括:
- 具有(如果可用的話也可以使用異步keywork)public property to access the reuslt(選項1)
- 有一個callback(選項2)
- resourcing to events
- 返回任務
- 返回IObservable(使用反應擴展,如果可用)
注:
- 有一個puplic屬性意味着你將需要應對呼叫者syncrhonization。
- 有一個回調,意味着一個奇怪的方式來調用該方法,並沒有明確的方式來等待。
- 使用事件可能會導致調用程序停留訂閱事件處理程序。
- 由於您正在使用線程池,因此返回一個任務看起來像是一種矯枉過正。
- 使用沒有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
很抱歉,但你可以epxlain我,什麼是使用的意思' Parallel.For'和'dynamic'? –