【问题标题】:Why is SyncLock not working here?为什么 SyncLock 在这里不起作用?
【发布时间】:2015-04-09 22:03:35
【问题描述】:

我正在开发一个为 CLR 应用程序提供异步通信的类库。

在 SslStream 上存在异步读取 (BeginRead),其中一个回调例程由多个流共享。 我不希望在调试期间并行处理回调,所以我创建了一个关键部分:

Private Sub Callback_Read(ByVal ar As IAsyncResult)
   Static OneAtATime As New Object
   SyncLock OneAtATime
      Dim ThisSslStream As SslStream = DirectCast(ar.AsyncState, SslStream)
      ...
   End SyncLock
End Sub

令我惊讶的是,这不起作用,至少当我在 SyncLock 块中设置断点时不起作用。多个流的回调同时在其中运行,无需在入口点等待前一个线程离开它。

单步执行简直是一场噩梦,尤其是当流同时被关闭(关闭)时:为流 1 执行行,为流 2 执行行,为 1 执行下一行,为 2 执行下一行,依此类推,贯穿整个街区。

我想也许你需要的不仅仅是一个通用的“新对象”,但后来我看到这里至少有一个关于堆栈溢出的答案,它说明了 SyncLock 正是我使用它的方式,只有“静态 X 作为新对象”来创建必须锁定的函数内的同步对象。

是不是因为回调实际上来自 .Net 框架之外的一个 win32 线程,所以 SyncLock 在这里不起作用?

【问题讨论】:

  • 该方法总是在同一个对象上调用,还是通过该类型的单独对象调用?
  • VB.NET 不使用“静态”,而是共享。还可以尝试将锁定对象移到方法范围之外。
  • @AllanS.Hansen 这不正确。 VB.NET 确实允许对局部变量使用 Static 修饰符,就像 VB6 一样。
  • @AllanS.Hansen Static在VB中确实存在,但与C#有不同的含义
  • @JamesThorpe 定义“正常”。它在这个上下文中的含义与它在 C 中的相同上下文中的含义相同。

标签: vb.net asynccallback synclock


【解决方案1】:
    Static OneAtATime As New Object

Static 关键字是 VB.NET 实现者脖子上的一块相当沉重的磨石。他们不得不支持它,因为它在以前的 Visual Basic 版本中经常使用,省略它会给想要更新他们的工具的程序员带来太多的困难。

但它的遗留行为与线程非常不兼容,线程是 .NET 中非常强烈支持的功能。以前不是问题,因为旧的 VB 版本不支持创建线程。为该语句生成的 MSIL 代码量大量。您应该使用 ildasm.exe 实用程序进行查看。

它之所以庞大是因为它需要做的事情。这是第一次输入方法时仅初始化一次变量。不是很困难,它会自动生成另一个布尔变量来跟踪。但更困难的部分是为每个单独的线程执行一次。换句话说,它具有 [ThreadStatic] 行为。

这就是要杀死你的原因,每个线程都有自己的 SyncLock。这就是为什么您根本没有观察到同步的原因:) 您需要将其移出方法并声明它Shared

【讨论】:

    【解决方案2】:

    我以前从未在VB中见过static局部变量的用法。存在这样的东西对我来说是新闻。我建议您改用传统方式并使用shared 类变量。

    public Class Test
       Private shared SyncRoot As Object = new Object()
    
       Private Sub Callback_Read(ByVal ar As IAsyncResult)
          SyncLock SyncRoot 
             Dim ThisSslStream As SslStream = DirectCast(ar.AsyncState, SslStream)
             ...
          End SyncRoot
       End Sub
    
    End Class
    

    【讨论】:

    • 糟糕,我把它移出功能时忘记共享了。
    猜你喜欢
    • 2013-05-16
    • 2019-02-10
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多