C# Asynchronous call without EndInvoke?(没有 EndInvoke 的 C# 异步调用?)
问题描述
以以下类为例.
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# 异步调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:没有 EndInvoke 的 C# 异步调用?


- 带有服务/守护程序应用程序的 Microsoft Graph CSharp SDK 和 OneDrive for Business - 配额方面返回 null 2022-01-01
- WebMatrix WebSecurity PasswordSalt 2022-01-01
- C#MongoDB使用Builders查找派生对象 2022-09-04
- Web Api 中的 Swagger .netcore 3.1,使用 swagger UI 设置日期时间格式 2022-01-01
- 良好实践:如何重用 .csproj 和 .sln 文件来为 CI 创建 2022-01-01
- MoreLinq maxBy vs LINQ max + where 2022-01-01
- C# 中多线程网络服务器的模式 2022-01-01
- 在哪里可以找到使用中的C#/XML文档注释的好例子? 2022-01-01
- 如何用自己压缩一个 IEnumerable 2022-01-01
- 输入按键事件处理程序 2022-01-01