当前位置: 首页 > 知识库问答 >
问题:

NetTcpBinding和Async/Await WCF阻塞

冀越
2023-03-14

我们正在创建一个共享WCF通道,用于异步操作:

var channelFactory = new ChannelFactory<IWcfService>(new NetTcpBinding {TransferMode = TransferMode.Buffered});

channelFactory.Endpoint.Behaviors.Add(new DispatcherSynchronizationBehavior(true, 25));
var channel = channelFactory.CreateChannel(new EndpointAddress(new Uri("net.tcp://localhost:80/Service").AbsoluteUri + "/Test"));

这将调用以下服务:

[ServiceContract]
public interface IWcfService
{
    [OperationContract]
    Task<MyClass> DoSomethingAsync();
}

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)]
public class WcfServiceImpl : IWcfService
{
    public Task<MyClass> DoSomethingAsync()
    {
        Thread.Sleep(4000);

        return Task.FromResult(new MyClass());
    }
}

[Serializable]
public class MyClass
{
    public string SomeString { get; set; }      
    public MyClass Related { get; set; }        
    public int[] Numbers { get; set; }
}

如果我们一次启动3个请求,并在响应上模拟一个长时间运行的任务:

        using ((IDisposable)channel)
        {
            var task1 = Task.Run(async () => await DoStuffAsync(channel));
            var task2 = Task.Run(async () => await DoStuffAsync(channel));
            var task3 = Task.Run(async () => await DoStuffAsync(channel));

            Task.WaitAll(task1, task2, task3);
        }
    }

    public static async Task DoStuffAsync(IWcfService channel)
    {
        await channel.DoSomethingAsync();

        Console.WriteLine("Response");

        // Simulate long running CPU bound operation
        Thread.Sleep(5000);

        Console.WriteLine("Wait completed");
    }
Response
// 5 second delay
Wait completed
// Instant
Response
// 5 second delay
Wait completed
// Instant
Response

我已经添加了一个我相信正在发生的事情的图像,这只发生在缓冲模式下,在流模式下主线程不会阻塞。

共有1个答案

孟健
2023-03-14

@下划线

我最近也试图解决同样的问题。尽管我无法确切地确定为什么transfermode.buffered在使用它的线程被释放之前导致WCF通道上的全局锁,但我在等待之后发现了类似的死锁问题。他们建议了一个解决办法,即在等待中添加runcontinuationsasynchronaly(),即await channel.dosomethingasync().runcontinuationsasynchronaly()whereruncontinuationsasynchronaly():

public static class TaskExtensions
{
    public static Task<T> RunContinuationsAsynchronously<T>(this Task<T> task)
    {
        var tcs = new TaskCompletionSource<T>();

        task.ContinueWith((t, o) =>
        {
            if (t.IsFaulted)
            {
                if (t.Exception != null) tcs.SetException(t.Exception.InnerExceptions);
            }
            else if (t.IsCanceled)
            {
                tcs.SetCanceled();
            }
            else
            {
                tcs.SetResult(t.Result);
            }
        }, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);

        return tcs.Task;
    }

    public static Task RunContinuationsAsynchronously(this Task task)
    {
        var tcs = new TaskCompletionSource<object>();

        task.ContinueWith((t, o) =>
        {
            if (t.IsFaulted)
            {
                if (t.Exception != null) tcs.SetException(t.Exception.InnerExceptions);
            }
            else if (t.IsCanceled)
            {
                tcs.SetCanceled();
            }
            else
            {
                tcs.SetResult(null);
            }
        }, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);

        return tcs.Task;
    }
}

它将WCF连续区分开。显然task.yield()也起作用。

 类似资料:
  • 本文向大家介绍JavaScript无阻塞加载和defer、async详解,包括了JavaScript无阻塞加载和defer、async详解的使用技巧和注意事项,需要的朋友参考一下 无阻塞加载 把js放在head里,浏览器是怎么去执行它的呢,是按顺序加载还是并行加载呢?在旧的浏览器下,都是按照先后顺序来加载的,这就保证了加载的js依赖不会发生问题。但是少部分新的浏览器已经开始允许并行加载js了,也就

  • 我正在尝试使用Tokio包装一个同步MQTT客户机库。代码需要通过通道连续接收消息,并将它们发送到异步代码中。我了解如何使用包装返回单个值的代码。但是如何将此应用于包装从通道连续接收消息的循环?

  • 我使用一些Java库来实现非异步的get和post请求。我曾经把这样的请求包装到未来,它为我解决了“等待问题”(我的意思是等待响应) 有可能吗?

  • 我试图理解为什么下面两个代码块会产生不同的结果。 代码块1按预期工作,并返回从数据库中查找的提供程序的数组。另一方面,代码块2返回函数数组。在理解promissione.all()和async/await时,我觉得缺少了一些简单的东西。 代码块的差异如下: > 块1:创建许诺函数数组,然后使用map运算符将其包装在异步函数中。 块2:许诺函数的数组被创建为异步函数。因此,不调用map运算符。 如果

  • 我有这门课。 我的spring配置是: 还有我的Mockito单元测试 如果我运行它,我获得了

  • 我正在做一个应用程序使用flutter框架。在此过程中,我遇到了Dart和中的关键字。谁能告诉我它们有什么不同吗?