Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 异步/等待按钮单击块UI_Vb.net - Fatal编程技术网

Vb.net 异步/等待按钮单击块UI

Vb.net 异步/等待按钮单击块UI,vb.net,Vb.net,我有一个简单的异步按钮和一个异步/等待函数。当我点击我的按钮时,我的界面冻结了。谁能解释一下我做错了什么 Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click LabelCounter.Text = "Running" LabelCounter.Text = await ComputeText() End Sub 这个功能是: Private Async F

我有一个简单的异步按钮和一个异步/等待函数。当我点击我的按钮时,我的界面冻结了。谁能解释一下我做错了什么

Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    LabelCounter.Text = "Running"
    LabelCounter.Text = await ComputeText()
End Sub
这个功能是:

Private Async Function ComputeText() As Task(Of String)
    Dim result as string = Await Task.Run(Function()
                                              'Thread.Sleep(2000)
                                              Dim i as Integer = 0
                                              While i <> 100000
                                                  i += 1
                                                  'block as other staff can access it as well from outside
                                                  SyncLock thisLock                                                   
                                                      LabelCounter.Invoke(Sub()
                                                                              LabelCounter.Text = i 
                                                                          End Sub)
                                                  End SyncLock
                                              End While

                                              Return "Done"
                                          End Function)
    Return result
End Function
专用异步函数ComputeText()作为任务(字符串的)
将结果变暗为字符串=等待任务。运行(函数()
《线程睡眠》(2000)
尺寸i为整数=0
而我呢
i+=1
“由于其他员工也可以从外部访问它,所以请阻止
同步锁定此锁定
LabelCounter.Invoke(Sub()
LabelCounter.Text=i
末端接头)
端同步
结束时
返回“完成”
终端功能)
返回结果
端函数
当我点击我的按钮时,我的界面冻结了

正如其他人所指出的,即使您使用的是
Async
/
wait
(这是正确的),问题在于
调用

Invoke
将中断UI线程并告诉它做些什么(在本例中,更新标签)。问题是后台线程正在以100000倍的速度中断UI

第二个难题是UI消息的优先级
WM_PAINT
(即,“重新绘制屏幕上需要更改的部分”)的优先级低于“运行此任意代码”消息。因此,用户界面实际上没有时间刷新,因为后台
Invoke
请求具有优先级,而且它们进入的速度太快

我建议使用标准的
IProgress
方法来报告进度,而不是更新标签和直接使用
Invoke
。这样做的好处是将UI显示与程序逻辑(在后台线程中运行)分离;此外,它还使用框架无关的方法(
IProgress
)而不是将您的逻辑专门绑定到WinForms(
Invoke

唯一真正的解决方案是限制后台更新。您可以在后台逻辑本身中执行此操作(即,仅每1000个周期左右发布一次更新),但这并不理想,因为1)这是业务逻辑中要解决的UI问题;2)它可以根据系统使用情况、CPU功率等随时间变化

因此,我建议让后台逻辑始终发送更新(使用
IProgress.Report
),并让
IProgress
实现对其进行限制。这最容易通过Rx实现。Lee Campbell有一个(这是更合适的解决方案),我有一个(这还没有更新到更合适的程度,但很容易设置一个预先限制的进度)

当我点击我的按钮时,我的界面冻结了

正如其他人所指出的,即使您使用的是
Async
/
wait
(这是正确的),问题在于
调用

Invoke
将中断UI线程并告诉它做些什么(在本例中,更新标签)。问题是后台线程正在以100000倍的速度中断UI

第二个难题是UI消息的优先级。
WM_PAINT
(即,“重新绘制需要更改的屏幕部分”)的优先级低于“运行此任意代码”因此,用户界面实际上没有时间刷新,因为后台
Invoke
请求占据优先权,而且它们进入的速度太快

我建议使用标准的
IProgress
方法来报告进度,而不是更新标签和直接使用
Invoke
。这样做的好处是将UI显示与程序逻辑(在后台线程中运行)分离;此外,它还使用框架无关的方法(
IProgress
)而不是将您的逻辑专门绑定到WinForms(
Invoke

唯一真正的解决方案是限制后台更新。您可以在后台逻辑本身中这样做(即,仅每1000个周期左右发布一次更新),但这并不理想,因为1)这是您的业务逻辑中要解决的UI问题;2)它可以根据系统使用情况、CPU功率等随时间变化


因此,我建议让后台逻辑始终发送更新(使用
IProgress.Report
),并让
IProgress
实现阻止更新。这是最容易通过接收完成。Lee Campbell有一个(这是更合适的解决方案),我有一个(尚未更新为更合适的解决方案,但很容易设置一个预先限制的进度)。

您使用的是
Invoke
,这是一个同步调用。嗯,调用
Invoke
十万次对性能来说可能不是最好的。@Glorin ah ok,这就是为什么它的frezzes mu UI(不知道Invoke是同步的)。但首先我必须更新这个标签,所以我必须使用Invoke(因为我在不同的线程上,所以我还必须进行同步锁定,因为我还有其他任务在更新标签。所以必须这样做,对吗?有没有其他方法可以实现?您使用的是
Invoke
,这是一个同步调用。那么,调用
Invoke
十万次可能是n。)ot将是性能最好的。@Glorin啊,好吧,这就是为什么它的frezzes mu UI(不知道调用是同步的)