我有这样的方法:
public IOrganizationService GetConnection(bool multi)
{
if(!multi)
{
Parallel.For(0, 1, i =>
{
dynamic _serviceobject= InitializeCRMService();
});
}
else
{
ThreadPool.QueueUserWorkItem
(
new WaitCallback
(
(_) =>
{
dynamic _serviceobject= InitializeCRMService();
}
)
);
}
}
我想从方法内部直接返回 _ 服务对象 * *。将两次撤回,即从if和一次撤回一次else循环解决了我的问题。请注意我使用多线程使用Pool线程的概念。如果两个线程并行运行,_serviceobjects将保持唯一。我不会在我的线程之间发生任何交互。
答案 0 :(得分:2)
WaitCallback
内的代码将在线程池中执行,并且可能在GetConnection
返回后执行此操作(这是执行异步操作的重点)。因此,由于它是另一个线程(具有另一个调用堆栈)并且它可能会在GetConnection
返回后执行,因此您无法从GetConnection
内部返回WaitCallback
。如果你真的想这样做,那么你必须让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。如果你想要异步操作,你需要一个asycrhonous API。如果你有一个异步API,那么你将不得不改变调用者的工作方式。
解决方案包括:
注意:
就个人而言,我会选择回调选项:
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
答案 1 :(得分:1)
您无法从WaitCallback处理程序内部返回它,因为代码中没有人将其返回。那只是一个回调。 您可能想尝试定义一个具有动态成员的自定义事件(派生自EventArgs)。
然后,您可以从工作人员入口点引发此事件,并随之发送动态对象。
您可以根据需要绑定到事件(即您要使用动态对象的位置)。
编辑(也显示一些代码):
在您拥有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)。