线程安全访问控件的最佳实践是什么 [英] What is the Best Practice for thread-safe access to controls

查看:33
本文介绍了线程安全访问控件的最佳实践是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以线程安全的方式访问控件花费的时间比看起来需要的时间长,因为我必须一遍又一遍地重复如下功能:

Accessing controls in a thread-safe manner takes longer to code than seems necessary because I have to repeat functions like the following over and over:

Private Sub SettbEnabled(tb As TrackBar, value As Integer)
    If tb.InvokeRequired Then
        tb.Invoke(Sub() tb.Enabled = value)
    Else
        tb.Enabled = value
    End If
End Sub

我最终可以为每个控件的每个方法和属性编写一个.

I could end up writing one for every method and property of every control.

有没有更有效的编码方式?理想情况下,整个应用程序只有一个子程序,无论我想访问哪些控件的哪些属性和方法,我都可以使用它?

Is there a more efficient way to code this? Ideally just one sub for the entire app, that I can use no matter what properties and methods of what controls I want to access?

推荐答案

在我看来,执行调用(像您一样)是最佳实践.我不认为有一般的最佳实践,但 Control.Invoke()Control.BeginInvoke() 方法被很多人使用.

In my opinion performing invocation (like you do) is the best practice. I don't think there is a general best practice, but the Control.Invoke() and Control.BeginInvoke() methods are used by many.

以线程安全的方式访问控件花费的时间比看起来需要的时间长,因为我必须一遍又一遍地重复如下功能

Accessing controls in a thread-safe manner takes longer to code than seems necessary because I have to repeat functions like the following over and over

我最终可以为每个控件的每个方法和属性编写一个.

I could end up writing one for every method and property of every control.

不一定,您仍然可以通过几种不同的方式简化代码.例如,TrackBar 派生自 System.Windows.Forms.Control 这意味着它可以被转换成 Control 类,因此您可以概括功能:

Not necessarily, you can still simplify your code in a few different ways. For instance, a TrackBar derives from System.Windows.Forms.Control which means it may be casted into the Control class, thus you can generalize the functions:

Private Sub SetEnabled(ctrl As Control, value As Integer)
    If ctrl.InvokeRequired Then
        ctrl.Invoke(Sub() ctrl.Enabled = value)
    Else
        ctrl.Enabled = value
    End If
End Sub

但实际上有一种更简单的方法:通过扩展方法.您可以创建一个扩展方法来自动执行调用和 InvokeRequired 检查.

But there's actually an even simpler way to do it: via Extension methods. You can create an extension method that will automatically perform the invocation and the InvokeRequired check for you.

多亏了 Sub()-lambda 表达式可以转换/转换为委托,您可以将其用作方法的参数并随意调用它:

Thanks to that a Sub()-lambda expression can be casted/converted into a delegate, you can use it as an argument for your method and call it at will:

Imports System.Runtime.CompilerServices

Public Module Extensions
    <Extension()> _
    Public Sub InvokeIfRequired(ByVal Control As Control, ByVal Method As [Delegate], ByVal ParamArray Parameters As Object())
        If Parameters IsNot Nothing AndAlso _
            Parameters.Length = 0 Then Parameters = Nothing 'If Parameters has a length of zero then no parameters should be passed.
        If Control.InvokeRequired = True Then
            Control.Invoke(Method, Parameters)
        Else
            Method.DynamicInvoke(Parameters)
        End If
    End Sub
End Module

有了这个扩展方法,你可以在任何派生自 System.Windows.Forms.Control 的类上调用它,你现在可以调用例如:

With this extension method, which you can call on any class that derives from System.Windows.Forms.Control, you will now be able to call for example:

Me.InvokeIfRequired(Sub() TrackBar1.Enabled = True)
'Me is the current form. I prefer to let the form do the invocation.

有了这个,你还可以调用更长的语句:

By having this you may also invoke longer statements:

Me.InvokeIfRequired(Sub()
                        Button1.Enabled = False
                        Label1.Text = "Something happened..."
                        ProgressBar1.Value += 5
                    End Sub)

这篇关于线程安全访问控件的最佳实践是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆