Vb.net 使用ThreadPool.QueueUserWorkItem(新建WaitCallback以创建通道)时如何同步返回?

Vb.net 使用ThreadPool.QueueUserWorkItem(新建WaitCallback以创建通道)时如何同步返回?,vb.net,multithreading,wcf,sync,Vb.net,Multithreading,Wcf,Sync,我需要在单独的线程上创建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

我需要在单独的线程上创建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
将返回空值,但有时它确实返回一个好的引用。我做错了什么

我根据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
Task.Factory.StartNew(
分()
svc=svcft.CreateChannel()
端接头
).继续(
分()
svcft=无
端接头
)
如果svc什么都不是,那么

抛出新异常(“创建服务引用失败”)”您的问题是一个争用条件。
ThreadPool.QueueUserWorkItem
后面的行可能有正确的值,也可能没有正确的值,这取决于当前线程和线程池线程的调度方式。这是错误的,我们不希望这样做

ThreadPool.QueueUserWorkItem
是以fire and forget方式在线程池线程上运行东西的旧方法。通常情况下,您不希望从那里重新同步(尽管您可以使用
事件
,但是,这些都是阻塞方式)

我们不想再阻止应用程序线程了。因此,出现了
Async/Await
TPL

以下是您可以做到这一点的方法:

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上,并且不想使用
async/await
,则可以直接使用
TPL
API

...
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/wait
capture
syncdhronizationcontext
自动)


感谢YK1的出色输入。你是对的,我在.Net 4上。所以我尝试了你推荐的TPL解决方案。我想一定是我做错了什么-变量svc仍然没有设置。下面是我代码的简化版本:Task.Factory.StartNew(Sub()svc=svcft.CreateChannel())。ContinueWith(Sub()svcft=Nothing)我已经更新了我的原始帖子以显示我的最新代码。它仍然不能解决这个问题。有什么想法吗?我想出来了-因为我需要在主线程中使用svc,.ContinueWith函数不会有帮助。只要我将其更改为.Wait()非常感谢您!YK1@user2434400:很抱歉延迟回复。您更新的问题不正确。使用svc的
代码应该在
ContinueWith
委托的
ContinueWith中,而不是在它之外。当然,
Wait()
将起作用,但它会阻塞主线程-您失去了在后台线程上创建对象的优势。
...
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())