Visual Basic 异步任务而不是同步任务

Posted

技术标签:

【中文标题】Visual Basic 异步任务而不是同步任务【英文标题】:Visual Basic Async Task instead Sync Task 【发布时间】:2016-09-20 00:24:04 【问题描述】:

我有一个执行同步任务的函数,我会做同样的事情,但使用异步任务。

我该怎么办?

这是代码:

Public Class Form1
    Private taskOUT As Task
    
Private Sub Button_Start_Click(sender As Object, e As EventArgs) Handles Button_Start.Click

        Dim freq As Double = TextBox1.Text
        Dim Amp As Double = TextBox2.Text
        Dim SPB As Double = TextBox3.Text
        Dim CPB As Double = TextBox4.Text
        '---------------------------------------
        Dim SCRate As Double = (freq * SPB) / CPB
        '---------------------------------------
        taskOUT = New Task()  'Crea un task
        taskOUT.AOChannels.CreateVoltageChannel("Dev1/ao0", "", -10, 10, AOVoltageUnits.Volts) 'Aggiunge un canale in Out
        taskOUT.Timing.SampleClockRate = SCRate
        taskOUT.Timing.ConfigureSampleClock("", SCRate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, 1000)
        '-----------------------------
        Dim ydata As Double()
        ydata = GenSin(freq, Amp, SCRate, SPB)
        '-------------------------------------------
        Dim writer As New AnalogSingleChannelWriter(taskOUT.Stream)
        writer.WriteMultiSample(False, ydata)
        taskOUT.Start()
    End Sub
    '-----------------------------------------------------------------------
    Public Shared Function GenSin( _
        ByVal freq As Double, _
        ByVal amp As Double, _
        ByVal sampleClockRate As Double, _
        ByVal samplePerBuffer As Double) As Double()

        Dim dt As Double
        Dim IntSample As Integer

        dt = 1 / sampleClockRate
        IntSample = CInt(SamplePerBuffer) - 1
        Dim y(IntSample - 1) As Double
        For i As Integer = 0 To IntSample - 1
            y(i) = amp * Math.Sin((2.0 * Math.PI) * freq * (i * dt))
        Next
        Return y
    End Function

    Private Sub Button_Stop_Click(sender As Object, e As EventArgs) Handles Button_Stop.Click
        taskOUT.Stop()
        taskOUT.Dispose()
    End Sub
End Class

【问题讨论】:

请不要以图片形式发布您的代码。真的很难读,而且SO还有语法高亮功能…… 谢谢,我已经更正了。 【参考方案1】:

应该这样做:

Private cancelSource As CancellationTokenSource

Sub StartWork
        cancelSource = New CancellationTokenSource
        Dim uiSyncContext = Tasks.TaskScheduler.FromCurrentSynchronizationContext
        Dim task = New Tasks.Task(Of Double())(Function() GenSin(3.4, 1.2, 100.0, 1000.0, cancelSource.Token))
        task.ContinueWith(Sub(dt) WriteData(dt.result), 
                          cancelToken, 
                          Tasks.TaskContinuationOptions.OnlyOnRanToCompletion, 
                          uiSyncContext)
    End Sub

    Function GenSin(freq As Double, amp As Double, rate As Double, spb As Double, cancelToken As CancellationToken) As Double()
        Dim dt As Double
        Dim isamp As Integer
        dt = 1 / rate
        isamp = CInt(spb) - 1
        Dim y(isamp - 1) As Double
        For i As Integer = 0 To isamp - 1
            If cancelToken.IsCancellationRequested Then Return Nothing
            y(i) = amp * Math.Sin(2 * Math.PI * freq * i * dt)
        Next
        Return y
    End Function

    Sub WriteData(results As Double()) 
        ' This is where you output the data
    End Sub

我已将 WriteData 拆分为一个单独的函数,因为我没有您的库。不过,您可能可以将其编写为 lamda 函数。要取消任务,只需从取消按钮处理程序中调用 cancelSource.cancel。

可能不需要 uiSyncContext - 它只是确保当您的任务完成时,管道中的下一步将在 UI 线程上运行。如果您不这样做,而您尝试以某种方式更新 GUI,则会出现错误。

我们首先创建一个任务,该任务通过运行 gensin 函数返回一个双精度数组。然后我们附加一个写入输出的延续任务。仅当第一个任务正常完成时,后续任务才会运行。如果你取消了它,或者它抛出了一个错误,这将不会运行。您可以通过这种方式将一大堆任务链接在一起,并为成功/失败/取消结果提供不同的路由

【讨论】:

以上是关于Visual Basic 异步任务而不是同步任务的主要内容,如果未能解决你的问题,请参考以下文章

js同步异步执行顺序setTimeOut面试题分析

js同步和异步

同步请求和异步请求区别

Js执行机制,同步任务异步任务

JS异步编程的5种方式

setTimeout的异步传输机制