繁体   English   中英

在c#中同步异步调用

[英]Synchronising an Asynchronous call in c#

我在工作中遇到了一个相当尴尬的困境。 我们需要在4个或5个不同的服务中创建用户,并以这样的方式进行设置:如果一个失败,它们都会失败。 它们封装在事务范围块中。

我们需要添加用户的服务之一需要telnet,并捏造一些数据。 还有其他方法可以做到这一点(这需要花钱)但是现在这就是我们所坚持的。 添加一个用户大约需要3分钟。 我们将努力将这一点大幅度降低,这可以想象,但这不是重点。 这个调用是异步的,必须要正常工作。 一句话是,该服务最多只能有10个连接。

我们的项目正在设置为批量创建用户。 因此,一次可能创建50个用户。 当只能通过telnet建立10个连接时,这会产生一个问题,并且处理过的用户除了telnet服务之外不可能花费很长时间。 我现在需要同步这个过程,所以其余的都不能继续,直到它完成。

我们正在使用带有异步调用的回调和委托来实现该功能。 什么是封装异步部分的最佳方法,并且在完成之前不会继续?

我们应该设置一个仅在呼叫结束时终止的循环吗? 线程库中有什么东西可以帮助吗? 我之前从未使用过线程,所以这对我来说是第一次。 有什么工具可以帮助解决这个问题?

编辑:

如果我使用BeginInvoke / EndInvoke模式,那么第一个委托内的异步调用是否也会对开始/结束表示支持?

例:

public void dele1(string message) {
    Console.Write(message);
    delegate2 del2 = new delegate2;
    del2();
    Console.Write("End of Delegate 2");
}

public void dele2() {
    // Long Processing
    Console.Write("Delegate 2");
}

public delegate void delegate1(String message);
public delegate void delegate2();

delegate1 del1 = new delegate1(dele1);
del1("Delegate 1").BeginInvoke;
del1().EndInvoke;
Console.Write("End of Delegate 1");

//预期输出(结束调用等待代理2完成):

Delegate 1
End of Delegate 2
Delegate 2
End of Delegate 1

//或(结束调用仅等待委托1完成但不是任何内部委托调用):

Delegate 1
End of Delegate 2
End of Delegate 1
Delegate 2

结束调用会等到第二个代理完成处理吗? 或者我是否需要在所有委托调用中使用调用模式?

您确实可以使用监视器,信号量,或者甚至可以旋转等待,直到您的异步方法调用完成。

但你也可以免费获得这个。 如果在先前使用BeginInvoke()启动的委托上调用EndInvoke() ,则会阻塞,直到异步工作完成。

不确定这是否有帮助,因为您必须使用此异步模式。 如果是这样,您将获得免费的异步执行(以及从异步转换回同步调用)。

有关此模式的详细信息,请查看在MSDN异步调用同步方法

我希望这有帮助!

听起来像你想要一个队列......如果有正在进行的请求,请添加到队列中(使用Monitor ); 当呼叫完成时,检查队列......

IAsyncResult有一个属性AsyncWaitHandle ,它为您提供一个等待句柄(如果有的话),它将在操作完成时发出信号。

因此,您可以使用WaitHandle.WaitAll (或.WaitAny )一次在许多句柄上执行非旋转等待。

你有几个选择。 以下是一些想法 -

首先,您可以使用ManualResetEvent来“阻止”主线程,直到您的异步操作全部完成。 想法是让主线程调用你的函数,然后执行event.WaitOne(),该函数负责设置事件。

或者,您可以尝试使用类似信号量的东西。 它旨在帮助处理这些情况,因为您可以将其限制为10次同时发生而不必担心自己会尝试处理它。 这可能是我的首选方法。

使用线程有两个原因:

  • 利用CPU资源,加快速度
  • 将几个同步状态机作为简单的方法编写,这使它们更具可读性

使用线程的缺点是:

  • 这真的很难

如果瓶颈是在远程计算机上等待3分钟,则可能值得注意的是多线程不会为您带来任何性能优势。 您可以编写整个thiing单线程,维护一组最多十个“状态机”对象并将它们移动到用户创建阶段,所有这些都来自一个线程,所有性能几乎没有差别。

因此,您可能正在寻找的是良好的可读代码布局,通过将用户创建操作转换为一系列调用,这些调用就像单个方法一样(如果您将它们作为线程运行,它们就是这样)。

获得它的另一种方法是通过迭代器方法,即包含yield return语句,这也为您提供了单方法可读性的优势。 我必须在上周连接这三次 这是Jeffrey Richter关于AsyncEnumerator的文章。

我对你如何使用TransactionScope有点不清楚(所以我可能不在基础上),但你可以创建可以发送到工作线程的DependentTransactions。 在所有DependentTransactions成功提交之后,您的顶级事务将不会提交,反之亦然。 我发现这是一种简单的方法,只要您调用的操作封装了提交/回滚功能(IEnlistmentNotification等),就可以跨线程执行全部或全部操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM