I'm working on replacing my old code that uses threads to a .NET 4.5 Task based system.
我正在努力将使用线程的旧代码替换为基于.NET 4.5 Task的系统。
I have the following sub that I wish to convert;
我有以下要转换的子项;
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
The Job class is one of my own, but importantly it contains an integer which is set to 1 if the job should be cancelled. So, the Delay function allows me to put a thread to sleep for X milliseconds, but if the job is cancelled during that time it will stop sleeping and return True.
Job类是我自己的一个,但重要的是它包含一个整数,如果要取消该作业,则该整数设置为1。因此,Delay函数允许我将线程置于休眠状态X毫秒,但如果在此期间取消作业,它将停止休眠并返回True。
I'm not sure how to do this with Await Task.Delay, here's my attempt;
我不知道怎么用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
The problem I'm having is that Async methods don't allow me to use ByRef, which means it won't be able to detect when the Job has been cancelled. Another issue is that await can't be used inside try/catch/finally or a synclock. I was under the impression you can write asynchronous code that looks like synchronous code. How can I get around these issues?
我遇到的问题是异步方法不允许我使用ByRef,这意味着它将无法检测作业何时被取消。另一个问题是await不能在try / catch / finally或synclock中使用。我的印象是你可以编写看起来像同步代码的异步代码。我该如何解决这些问题?
2 个解决方案
#1
3
You're not actually mutating the Job
variable in the body of your method, so you shouldn't be passing it by reference at all, you should be passing it by value.
你实际上并没有在方法体中改变Job变量,所以你根本不应该通过引用传递它,你应该按值传递它。
That is, unless Job
is actually a mutable value type instead of a reference type, in which case that is your problem and you should fix it by not using a mutable value type here.
也就是说,除非Job实际上是一个可变值类型而不是引用类型,在这种情况下这是你的问题,你应该通过不使用可变值类型来修复它。
It's also worth noting that if you wish to use an object to encapsulate the possible cancellation of an asynchronous operation you should use CancellationToken
(and the accompanying CancellationTokenSource
). It will provide all of the functionality that you need, and of particular note, it will handle all of the proper synchronization such that you won't run into any problems accessing it from multiple threads. It also happens to be a reference type.
值得注意的是,如果您希望使用对象来封装异步操作的可能取消,则应使用CancellationToken(以及随附的CancellationTokenSource)。它将提供您需要的所有功能,特别注意,它将处理所有正确的同步,这样您就不会遇到从多个线程访问它的任何问题。它也恰好是一种参考类型。
If you accept a CancellationToken
you'll also be able to pass it to Task.Delay
, allowing it to complete when the token is cancelled, rather than forcing your method to wait until the delay is over to return false
.
如果你接受CancellationToken,你也可以将它传递给Task.Delay,允许它在令牌被取消时完成,而不是强迫你的方法等到延迟结束后返回false。
#2
1
Make sure to declare Job
as a Class
, and not a Structure
. This will allow it to be passed ByVal
(the default) and work perfectly in your code as described, as it will be a reference type and mutations handled externally will be visible within your method.
确保将Job声明为类,而不是结构。这将允许它传递ByVal(默认值)并在所描述的代码中完美地工作,因为它将是一个引用类型,并且在您的方法中可以看到外部处理的突变。
Since you don't change Job
inside of your function, it shouldn't be passed ByRef
.
由于您不在函数内部更改Job,因此不应传递ByRef。
#1
3
You're not actually mutating the Job
variable in the body of your method, so you shouldn't be passing it by reference at all, you should be passing it by value.
你实际上并没有在方法体中改变Job变量,所以你根本不应该通过引用传递它,你应该按值传递它。
That is, unless Job
is actually a mutable value type instead of a reference type, in which case that is your problem and you should fix it by not using a mutable value type here.
也就是说,除非Job实际上是一个可变值类型而不是引用类型,在这种情况下这是你的问题,你应该通过不使用可变值类型来修复它。
It's also worth noting that if you wish to use an object to encapsulate the possible cancellation of an asynchronous operation you should use CancellationToken
(and the accompanying CancellationTokenSource
). It will provide all of the functionality that you need, and of particular note, it will handle all of the proper synchronization such that you won't run into any problems accessing it from multiple threads. It also happens to be a reference type.
值得注意的是,如果您希望使用对象来封装异步操作的可能取消,则应使用CancellationToken(以及随附的CancellationTokenSource)。它将提供您需要的所有功能,特别注意,它将处理所有正确的同步,这样您就不会遇到从多个线程访问它的任何问题。它也恰好是一种参考类型。
If you accept a CancellationToken
you'll also be able to pass it to Task.Delay
, allowing it to complete when the token is cancelled, rather than forcing your method to wait until the delay is over to return false
.
如果你接受CancellationToken,你也可以将它传递给Task.Delay,允许它在令牌被取消时完成,而不是强迫你的方法等到延迟结束后返回false。
#2
1
Make sure to declare Job
as a Class
, and not a Structure
. This will allow it to be passed ByVal
(the default) and work perfectly in your code as described, as it will be a reference type and mutations handled externally will be visible within your method.
确保将Job声明为类,而不是结构。这将允许它传递ByVal(默认值)并在所描述的代码中完美地工作,因为它将是一个引用类型,并且在您的方法中可以看到外部处理的突变。
Since you don't change Job
inside of your function, it shouldn't be passed ByRef
.
由于您不在函数内部更改Job,因此不应传递ByRef。