如何在多任务窗口窗体应用程序中调整从端口读取的值

Posted

技术标签:

【中文标题】如何在多任务窗口窗体应用程序中调整从端口读取的值【英文标题】:How to Adjust read values from port in a multitask windows form application 【发布时间】:2018-04-08 05:35:42 【问题描述】:

我想从其中一个系统端口读取信息并使用这些数据来(实时)更新 Windows 窗体控件(例如文本框、标签等)的值,同时我想插入这些将每个控件对应的值存入数据库(ms sql server)。

为了更新每个控件的值,我使用 TPL 为每个控件编写了类似于以下代码的代码。我的问题是如何在给定时间调整(或同步)与每个控件对应的值。

Task.Factory.StartNew(() =>

    tag = true;
    while (tag)
    
        string value = readDataFromPort();
        databaseObj.lable1 = value;
        var task = Task.Factory.StartNew(() =>
        
             label1.Text = value;
        , CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
        System.Threading.Thread.Sleep(100);
        task.Wait();
    
);

我的意思是,例如数据库记录中的lable1和lable2的值都与时间T1有关,接下来的值与T2时间有关,一直持续到断开连接(Tag值等于false)。另外,如果您知道,请建议使用其他技术(如线程)的更好方法。我在 Visual Studio 2013 上使用 .NET Framework 4.5。

【问题讨论】:

数据库记录中 lable1 和 lable2 的值都与时间 T1 相关 - 我看不到这里提到的时间。据我了解这篇文章,您希望更新 UI 中的所有控件,然后在收到数据包时更新它们的数据库值。是这样吗? 不清楚你在问什么,请改写你的问题。 @o_O,我想更新 UI 中的所有控件,然后在收到数据包时“设置新值”(不更新)它们的数据库值(在具有相应时间戳的新记录中) . 我没怎么用过Task类,但是我一直在用Threads。基于线程的答案就足够了吗?还有来自接收到的数据的某种标识符会告诉,哪个控件应该使用特定接收到的字符串进行更新 @o_O,我使用 Task 类,因为它更容易,但我想要做的也可以使用线程。可以使用 controlX.updateValue = readData.controlX() 来访问每个控件对应的读取数据。 【参考方案1】:

正如我在 cmets 中告诉你的,实现这一点的一种方法是使用线程,

但首先要创建一个static 扩展名,例如:

public static class MyExtensions

   public static void InvokeBy(this Control ctl, MethodInvoker method)
   
      if (ctl.InvokeRequired)
          ctl.Invoke(method);
      else method();
   

在您的主类中使用这个static 类,您将在其中接收数据包并更新控制。使用这个static 类是为了避免在访问控件并将其内容从子线程更新到主UI 线程时跨线程异常

现在实际工作:

Thread thread = new Thread(() =>

     this.InvokeBy(() =>
     
           tag = true;
           while (tag)
           
               string value = readDataFromPort();
               //I'm still not sure about the above method, what would be the value of 
               //control IDENTIFIER you might get 
               //along with the packet. As you said in the comments using:
               //"controlX.updateValue = readData.controlX()",
               //you can differentiate controls with their respective packets.
               //So let'say you get the Control's NAME as IDENTIFIER, then:
               string controlName = "Control Name goes here";

               var controls = this.Controls;
               //you can use Controls.OfType<Label>() to spefically 
               //pick a certain type of control from the UI

               foreach (Control control in controls)
               
                   if (control.Name == controlName)
                   
                        control.InvokeBy(() =>
                        
                             //replace this with database object of the control
                             databaseObj.lable1 = value;

                             //If you've got some other differentiation to be
                             //used among the controls, implement if-else conditions
                             //and then update their respective value
                             control.Text = value;
                        );
                   
               
           
       );
   );
thread.SetApartmentState(ApartmentState.STA);
thread.Start();

希望您对如何开始使用它有所了解!

【讨论】:

我不知道扩展方法!我试试看…… 将静态类保持在与主类相同的命名空间下,以便轻松访问其扩展方法 请您解释一下“thread.SetApartmentState(ApartmentState.STA);” STA 表示单线程应用程序。它用于管理您在应用程序中创建的线程的访问级别。您也可以设置 MTA 即多线程应用程序,但是您的控制访问会引起一些麻烦。您可以在apartment state 阅读更多相关信息 正如我所说,我使用专用任务来更新每个控件的值,并且我正在寻找一种方法来调整时间戳(每个控件的值被更新的时间)所有控件的值,但是在您的方法中,仅使用一个线程来更新所有控件的值,并且与每个控件对应的所有值都具有相同的时间戳。哪种方法更好?

以上是关于如何在多任务窗口窗体应用程序中调整从端口读取的值的主要内容,如果未能解决你的问题,请参考以下文章

如何实现Winform窗体应用程序的字体和窗体大小不跟随分辨率改变

如何使用 VBA 从 Excel 用户窗体中读取复选框的值

如何在windows窗体里面添加窗口

C# WinForm中,如何判断窗口已打开

.net中如何动态改变Label控件的位置

在 Windows 窗体控件中调整大小以及窗体调整大小