如何在Async函数中没有ByRef处理?

时间:2014-09-10 19:30:59

标签: .net vb.net asynchronous task

我正在努力将使用线程的旧代码替换为基于.NET 4.5 Task的系统。

我有以下要转换的子目录;

Public Function Delay(Milliseconds As Integer, ByRef Job As Job) As Boolean
   For i As Integer = 1 To CInt(Milliseconds / 100)
      Thread.Sleep(100)
      If Job.IsCancelled Then Return True
   Next
   Return False
End Function

Job类是我自己的一个,但重要的是它包含一个整数,如果要取消该作业,则该整数设置为1。因此,Delay函数允许我将一个线程置于休眠状态X毫秒,但如果在此期间取消该作业,它将停止休眠并返回True。

我不知道怎么用Await Task.Delay做这个,这是我的尝试;

  Public Async Function Delay(Milliseconds As Integer, Job As Job) As Tasks.Task(Of Boolean)
    For i As Integer = 1 To CInt(Milliseconds / 100)
      Await Tasks.Task.Delay(100)
      If Job.IsCancelled Then Return True
    Next
    Return False
  End Function

我遇到的问题是Async方法不允许我使用ByRef,这意味着它将无法检测作业何时被取消。另一个问题是await不能在try / catch / finally或synclock中使用。我的印象是你可以编写看起来像同步代码的异步代码。我该如何解决这些问题?

2 个答案:

答案 0 :(得分:4)

您实际上并没有改变方法正文中的Job变量,因此您根本不应该通过引用传递它,您应该按值传递它。

也就是说,除非Job实际上是一个可变值类型而不是引用类型,在这种情况下 是你的问题,你应该通过不使用可变值类型来修复它这里。

还值得注意的是,如果您希望使用对象来封装异步操作的可能取消,则应使用CancellationToken(以及随附的CancellationTokenSource)。它将提供您需要的所有功能,特别注意,它将处理所有正确的同步,这样您就不会遇到从多个线程访问它的任何问题。它也恰好是一种参考类型。

如果您接受CancellationToken,您也可以将其传递给Task.Delay,允许在令牌取消时完成,而不是强制您的方法等到延迟已结束return false

答案 1 :(得分:1)

请务必将Job声明为Class,而不是Structure。这将允许它传递ByVal(默认值)并在您的代码中完美地工作,因为它将是一个参考类型,并且在您的方法中可以看到外部处理的突变。

由于您未在函数内部更改Job,因此不应将其传递给ByRef