0

別のスレッドで WCF ChannelFactory を作成する必要があります。私が今直面している問題は、変数svcが常に値を返すとは限らないことです:

   ...
   Dim svc As T = Nothing
   Dim svcft As New DuplexChannelFactory(Of T)(caller, ep)
   ThreadPool.QueueUserWorkItem(New WaitCallback(Sub(obj) svc = svcft.CreateChannel()))
   ...

ほとんどのsvc場合、null 値が返されますが、適切な参照が返されることもあります。私は何を間違っていますか?

以下のYK1のコメントに従ってコードを修正しました。それでも問題は解決しません-svcはまだ常に設定されているわけではありません:

Task.Factory.StartNew(
    Sub()
        svc = svcft.CreateChannel()
    End Sub
).ContinueWith(
    Sub()
        svcft = Nothing
    End Sub
)
If svc Is Nothing Then
    Throw New Exception("Creating service reference failed.") '<== get the error here...
End If
4

1 に答える 1

1

あなたの問題は競合状態です。次の行は、現在のスレッドとスレッド プール スレッドがどのようにスケジュールされているかに基づいて、ThreadPool.QueueUserWorkItem正しい値を持つ場合と持たない場合があります。svcこれは悪いことであり、私たちはこのようにしたくありません。

ThreadPool.QueueUserWorkItemスレッドプールスレッドで実行する古い方法は、火と忘れの方法です。通常、そこから同期し直すことは望ましくありません (ただし、 を使用することはできますがevents、これらはすべてブロック方法です)。

もうアプリケーション スレッドをブロックしたくありません。だから、入ってくるAsync/AwaitTPL.

これを行う方法は次のとおりです。

Async Function MyFuncAsync(Of T)() As Task
   ...
   Dim svc As T = Nothing
   Dim svcft As New DuplexChannelFactory(Of T)(caller, ep)
   svc = Await Task.Run(Funtion() svcft.CreateChannel())
   ...
End Function

.NET 4.5 を使用しておらず、使用したくない場合は、 API を直接async/await使用できます。TPL

...
Dim svc As T = Nothing
Dim svcft As New DuplexChannelFactory(Of T)(caller, ep)
Task.Factory.StartNew(
    Sub() 
        svc = svcft.CreateChannel()
    End Sub
).ContinueWith(
    Sub(t) 
        `rest of code here
    End Sub
)

メイン スレッドが UI スレッド (WPF/Winforms) である場合、UI スレッドで同期したい場合は、継続を UI スレッドで実行することができます。(async/await上記は自動的にキャプチャsyncdhronizationcontextされます)。

...
Dim svc As T = Nothing
Dim svcft As New DuplexChannelFactory(Of T)(caller, ep)
Task.Factory.StartNew(
    Sub() 
        svc = svcft.CreateChannel()
    End Sub
).ContinueWith(
    Sub(t) 
        `rest of code here
    End Sub,
TaskScheduler.FromCurrentSynchronizationContext())
于 2013-07-23T21:00:59.860 に答える