问题描述
以以下类为例.
public class A
{
// ...
void Foo(S myStruct){...}
}
public class B
{
public A test;
// ...
void Bar()
{
S myStruct = new S();
test.Foo(myStruct);
}
}
现在,我希望方法调用 test.Foo(myStruct) 是一个异步调用(即发即弃").bar-method 需要尽快返回.关于委托、BeginInvoke、EndInvoke、ThreadPool 等的文档并没有帮助我找到解决方案.
Now, I want the method-call test.Foo(myStruct) to be an asynchronous call ('fire-and-forget'). The bar-method needs to return as soon as possible. Documentation around delegates, BeginInvoke, EndInvoke, the ThreadPool etc. isn't helping me find a solution.
这是一个有效的解决方案吗?
Is this a valid solution?
// Is using the `EndInvoke` method as the callback delegate valid?
foo.BeginInvoke(myStruct, foo.EndInvoke, null);
推荐答案
你不需要调用 EndInvoke
;不叫它仅仅意味着:
You are not required to call EndInvoke
; not calling it merely means:
- 您没有从方法中获得返回值.
- 在方法执行过程中抛出的任何异常都会消失.
听起来您想一劳永逸",所以最简单的方法是使用匿名委托,例如:
It sounds like you want to 'fire-and-forget', so the easiest way to do this is to use an anonymous delegate, for example:
var del = new Action(foo.Bar);
del.BeginInvoke(iar =>
{
try
{
del.EndInvoke(iar);
}
catch (Exception ex)
{
// Log the message?
}
}, null);
当你执行这段代码时会发生这种情况:
This is what happens when you execute this code:
- 为委托分配(简单地说)一个新线程.
- 线程被赋予了委托
del
和匿名委托 (iar => ...
). - 线程执行
del
. - 当它完成执行(或发生异常)时,将存储结果或异常并执行匿名委托.
- 在匿名委托中,当调用
EndInvoke
时,要么返回方法的结果,要么抛出异常(如果发生异常).
- A new thread is allocated (put simply) for the delegate.
- The thread is given the delegate
del
and the anonymous delegate (iar => ...
). - The thread executes
del
. - When it is finished executing (or an exception occurs) the result or exception is stored and the anonymous delegate is executed.
- Inside the anonymous delegate, when
EndInvoke
is called the result from the method is either returned, or the exception is thrown (if one occurred).
请注意,上面的示例与:
Note that the above example is very different from:
// This is pointless and is still, essentially, synchronous.
del.EndInvoke(del.BeginInvoke(null, null));
您应该始终调用End*
.我从来没有发现不调用它会出现问题的场景,但这是一个实现细节,并且是 依赖于未记录的行为.
You should always call End*
. I've never found a scenario where not calling it presents a problem, however that is an implementation detail and is relying on undocumented behavior.
最后,如果抛出异常,您的解决方案将使进程崩溃,如果您不关心异常,您可以简单地将 null 作为委托传递 ( 作为最后一个示例,您正在寻找的可能是:del.BeginInvoke(myStruct, null, null);
).
Finally your solution would crash the process if an exception is thrown, you can simply pass null as the delegate if you don't care about the exception ( So as a final example what you are looking for is probably:del.BeginInvoke(myStruct, null, null);
).
public class A
{
// ...
void Foo(S myStruct){...}
void FooAsync(S myStruct)
{
var del = new Action<S>(Foo);
del.BeginInvoke(myStruct, SuppressException, del);
}
static void SuppressException(IAsyncResult ar)
{
try
{
((Action<S>)ar.AsyncState).EndInvoke(ar);
}
catch
{
// TODO: Log
}
}
}
这篇关于没有 EndInvoke 的 C# 异步调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!