正确的多线程使用.Net Web引用客户端

时间:2012-04-25 02:15:23

标签: .net multithreading soap task-parallel-library webservice-client

我必须使用.net 2.0时代.asmx网络服务,我没有构建,无法控制。但是,该服务非常可用,可以处理这个问题。

我需要帮助的是客户端,并从可靠的角度正确使用visual studio生成的客户端代理。目前我正在使用Web引用,但如果需要可以切换到服务引用。我对WCF一无所知。

我读的越多,我就越迷惑自己。

我的具体问题:

鉴于visual studio生成的soap客户端代理可以产生以下方法:

Foo();
FooAsync();
FooCompleted;

Bar();
BarAsync();
BarCompleted;
  1. 应该/我可以从多个线程调用Foo(),就像在Parallel.ForEach中一样吗?
  2. 我应该/可以在并行foreach中调用FooAsync()吗?这似乎是多余的,因为我已经在另一个线程了?这样做是否安全?
  3. 我应该/可以在一个线程上调用FooAsync(),同时在另一个线程上调用BarAsync()吗?
  4. 这些生成的soap服务类似乎实现了EAP模式。我对pfx / tpl的东西很陌生,但我一直在将任务看作是更好地管理其中一些的方法吗?我已经看到了如何使用TaskCompletionSource使用Task包装EAP的示例。这是更好的方法吗?

1 个答案:

答案 0 :(得分:2)

  1. 您可以根据需要在尽可能多的线程上调用Foo()(您必须自己决定是否 )。它们(就像你建议的那样)运行,就像它们并行运行一样。

  2. 我已经使用下面的任务并行库(TPL)提供了您想要的示例。如果你已经为FooAsync()生成了一个线程,那么为Foo()生成一个线程是多余的,但这取决于你正在做什么或想要做什么。通常,您可以从UI线程调用Foo(),然后在另一个线程上启动FooAsync()

    private void Foo()
    {
        // Get TaskScheduler to facilitate manipulation of GUI on UI Thread.
        TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
    
        // Cancellation support.
        CancellationTokenSource cancelSource = new CancellationTokenSource();
        CancellationToken token = cancelSource.Token;
    
        // Spin-off onto background thread.
        Task<bool> asyncFooTask = null;
        asyncFooTask = Task.Factory.StartNew<bool>(() => asyncFoo(uiScheduler, token, _dynamic), token);
    
        // Continuation/call-back/error-handling.
        asyncTask.ContinueWith(task =>
        {
            // Check task status.
            switch (task.Status)
            {
                // Handle any exceptions to prevent UnobservedTaskException.             
                case TaskStatus.RanToCompletion:
                    if (asyncTask.Result)
                        // Success. Do stuff.
                    else
                        // Failed. Do stuff.
                    break;
                case TaskStatus.Canceled:
                    if (task.Exception != null)
                        // Cancelled with exception.
                    else
                        // User cancelled.
                    break;
                case TaskStatus.Faulted:
                    if (task.Exception != null)
                        // AggregateException thrown by antecident.
                    else
                        // Task failed...
                    break;
            }
            return;
        }, TaskScheduler.FromCurrentSynchronizationContext());
    }
    
  3. 有关TPL及其使用的精彩介绍,请参阅此link。另外,有关通用线程(以及一些不同的伪装)的更多信息,请参阅J. Albahari's Threading Page

    3这完全是主观的,取决于你想做什么。与答案1建议的一样,您可以根据需要在多个线程上调用这些方法中的每一个。

    4有关EAP模式的一个很好的例子see here。正如您将看到的,它基本上就是我在上面提供的内容。对于上述方法,我假设您希望在and 'BarCompleted()FooAsync()完成后运行'FooCompleted()BarAsync()。在这种情况下,我会说EPL模式正是你想要的。

    我希望这会有所帮助。