.net visual studio生成的Web服务客户端是否线程安全?

.net visual studio生成的Web服务客户端是否线程安全?,.net,vb.net,multithreading,web-services,wcf,.net,Vb.net,Multithreading,Web Services,Wcf,我们在一个项目中创建了一个服务引用 现在,我们在应用程序启动时创建一个实例。 同样,当应用程序统计时,我们为Service.Method1Completed,Service.Method2Completed等添加一个事件处理程序 然后在特定事件上,我们调用Service.Method1Async,Service.Method2Asyncect。注意,这些调用是由不同的线程发出的 但在某些计算机上,事件处理程序从未触发,因此我们开始检查FirstChanceExceptions,因为当发生这种情况

我们在一个项目中创建了一个服务引用

现在,我们在应用程序启动时创建一个实例。 同样,当应用程序统计时,我们为
Service.Method1Completed
Service.Method2Completed
等添加一个事件处理程序

然后在特定事件上,我们调用
Service.Method1Async
Service.Method2Async
ect。注意,这些调用是由不同的线程发出的

但在某些计算机上,事件处理程序从未触发,因此我们开始检查
FirstChanceExceptions
,因为当发生这种情况时,会出现以下
FirstChanceExceptions

System.Net.Sockets.SocketException提供的参数无效。
vid System.Net.Sockets.Socket.SETSOCKET选项(SocketOptionLevel optionLevel,SocketOptionName optionName,Int32 optionValue,布尔值 (无声)

System.ObjectDisposedException无法访问已处置的对象。 Objectname:System.Net.Sockets.NetworkStream。视频 System.Net.Sockets.NetworkStream.UnsafeBeginWrite(字节[]缓冲区,Int32 偏移量、Int32大小、异步回调、对象状态)

System.Net.WebException请求已取消。
vid System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)

这是使用服务引用的无效方式吗? 如果是这样的话,我如何在使用异步方法处理事件的同时正确地使用同步调用(请注意,im在.net 4.0和VS 2010上运行,因此
wait
是不可能的

服务器代码:

<ServiceContract()>
Public Interface IService1

    <OperationContract()>
    Function GetData(ByVal value As Integer) As String

End Interface

<ServiceBehavior(ConcurrencyMode:=ConcurrencyMode.Multiple, InstanceContextMode:=InstanceContextMode.Single, UseSynchronizationContext:=False)>
Public Class Service1
    Implements IService1

    Public Sub New()
    End Sub

    Public Function GetData(ByVal value As Integer) As String Implements IService1.GetData
        Return String.Format("You entered: {0}", value)
    End Function

End Class

它们不是线程安全的(例如,
ClientBase
不是)。但它们的制造和破坏成本很低。每个线程创建一个,甚至每个调用创建一个。无需同步。

ClientBase可能不是线程安全的*因此派生代理也不是线程安全的,因此您不能以这种方式使用它们

您可以创建线程安全的基类,并自定义生成代理类

state
参数可用于将响应与传出请求相匹配。您将在回调事件的IAsyncResult.AsyncState中找到它

需要担心的一件事是,当多个请求通过同一个通道发送时,由于某些/任何原因,通道出现故障


*再看看这个问题:

我创建了一个新项目,在这个项目中,我对一个Web服务进行了大量调用,每个请求有一个客户端,很抱歉,我仍然得到
ObjectDisposedException
(它们只是第一次出现的异常,我从未得到完整的回调…)好的,代码看起来不错。线程是一个风险区域,但除了count变量之外,我看不到任何共享状态。出于测试目的,将代码设为单线程。这个特定的问题还会发生吗?我只是尝试将代码更改为在MultipleClientInstances中只启动一个线程,然后我将调用数从400增加到4000,但仍然会出现错误……这不是线程问题。通过HTTP调用服务,并使用Fiddler查看HTTP和网络级别的错误。你发现了什么错误?如果有,发布有意义的截图。当我针对IIS运行客户端时,此错误停止发生,但我仍然发现服务器上的某些错误可能导致客户端内存泄漏,这令人不安。。。
<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior>
        <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
        <serviceMetadata httpGetEnabled="true"/>
        <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
        <serviceDebug includeExceptionDetailInFaults="false"/>
        <serviceThrottling maxConcurrentCalls="1000" maxConcurrentSessions="1000" maxConcurrentInstances="1000" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <bindings>
    <customBinding>
      <binding>
        <binaryMessageEncoding>
          <readerQuotas maxArrayLength="5242880" />
        </binaryMessageEncoding>
        <httpTransport maxBufferPoolSize="52428800" maxReceivedMessageSize="5242880" maxBufferSize="5242880" authenticationScheme="Anonymous" />
      </binding>
    </customBinding>
  </bindings>
  <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Imports System.Threading
Imports System.IO

Module Module1
    Dim errorQueue As New System.Collections.Concurrent.ConcurrentBag(Of String)
    Dim count As Integer

    Sub Main()
        AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf CurrentDomain_UnhandledException
        AddHandler AppDomain.CurrentDomain.FirstChanceException, AddressOf AppDomain_FirstChanceException

        MultipleClientInstances()
        Console.WriteLine("Calls are in progress, press any key when they are done!")
        Console.ReadKey()

        Thread.MemoryBarrier()
        errorQueue.Add("Number of requests remaining " + count.ToString())
        Dim line As String = ""
        Using writer As New StreamWriter("output.log")
            While (errorQueue.TryTake(line))
                writer.WriteLine(line)
            End While
        End Using
    End Sub

    Private Function GetClient() As ServiceReference1.Service1Client
        Dim client As New ServiceReference1.Service1Client()
        AddHandler client.GetDataCompleted, AddressOf client_GetDataCompleted
        client.Open()
        Return client
    End Function

    Private Sub MultipleClientInstances()
        Console.WriteLine("Making calls!")
        For i As Integer = 0 To 10
            Dim t As New Thread(AddressOf MakeCallsWithNewClients)
            t.Start()
        Next
    End Sub

    Private Sub MakeCallsWithNewClients()
        For i As Integer = 0 To 400
            Interlocked.Increment(count)
            Dim client As ServiceReference1.Service1Client = GetClient()
            client.GetDataAsync(i, True)

            While (Thread.VolatileRead(count) > 20)
                Thread.Sleep(5)
            End While
        Next
    End Sub

    Private Sub client_GetDataCompleted(sender As Object, e As ServiceReference1.GetDataCompletedEventArgs)
        Dim value As Integer = Interlocked.Decrement(count)
        Console.WriteLine(value)

        Dim client As ServiceReference1.Service1Client = CType(sender, ServiceReference1.Service1Client)
        RemoveHandler client.GetDataCompleted, AddressOf client_GetDataCompleted
        client.Close()
    End Sub

    Private Sub CurrentDomain_UnhandledException(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)
        If (e.ExceptionObject IsNot Nothing AndAlso e.ExceptionObject.GetType().IsSubclassOf(GetType(Exception))) Then
            If (e.IsTerminating) Then
                Console.WriteLine("Fatal exception occurred termination application, " + CType(e.ExceptionObject, Exception).ToString())
            Else
                Console.WriteLine("Unhandled exception occurred, " + CType(e.ExceptionObject, Exception).ToString())
            End If
        Else
            If (e.IsTerminating) Then
                Console.WriteLine("Fatal exception occurred termination application, " & e.ExceptionObject.ToString())
            Else
                Console.WriteLine("Unhandled exception occurred, " & e.ExceptionObject.ToString())
            End If
        End If
        errorQueue.Add("UnhandledException: " + e.ExceptionObject.ToString())
    End Sub

    Private Sub AppDomain_FirstChanceException(ByVal sender As Object, ByVal e As Runtime.ExceptionServices.FirstChanceExceptionEventArgs)
        Console.WriteLine("FirstChanceException: " + e.Exception.ToString())
        errorQueue.Add("FirstChanceException: " + e.Exception.ToString())
    End Sub
End Module