在 do while 循环内检查多个 checkbox.checked 状态

2024-04-07

我在上一个问题中问过如何“线程化 2 个表单以同时使用 C#” https://stackoverflow.com/questions/40450905/threading-2-forms-to-use-simultaneously-c-sharp.
我现在意识到我不够明确并且问错了问题。

这是我的场景:
我有一些从本地服务器收到的数据,我需要将其写入文件。 这些数据以我无法控制的恒定时间速率发送。
我想做的是用一个 winform 来初始设置 tcp 流,然后单击一个按钮开始读取 tcp 流并将其写入文件,同时启动另一个带有多个检查的 winform -我需要检查选中状态并将该信息同时添加到同一文件中的框。
当按下不同的按钮时,此处理将停止,关闭流、文件和第二个 winform。 (此按钮位置对于任何 winform 都不是特别强制的)。

由于这个取消按钮(在我尝试实现第二种形式之前),我使用后台工作人员能够异步取消用于读取流和写入文件的 do while 循环。

    private void bRecord_Click(object sender, EventArgs e)
    {
        System.IO.StreamWriter file = new System.IO.StreamWriter(AppDomain.CurrentDomain.BaseDirectory + DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss") + ".xml", true);

        data_feed = client.GetStream();
        data_write = new StreamWriter(data_feed);
        data_write.Write("<SEND_DATA/>\r\n");
        data_write.Flush();

        exit_state = false;
        string behavior = null;

        //code to launch form2 with the checkboxes
        //...

        worker = new BackgroundWorker();
        worker.WorkerSupportsCancellation = true;

        worker.DoWork += new DoWorkEventHandler((state, args) =>
        {
            do
            {
                int var = data_feed.ReadByte();
                if (var != -1)
                {
                    data_in += (char)var;

                    if (data_in.IndexOf("\r\n") != -1)
                    {
                        //code to check the checkboxes state in form2
                        //if (form2.checkBox1.Checked) behavior = form2.checkBox1.Text;
                        //if (form2.checkBoxn.Checked) behavior = form2.checkBoxn.Text;  

                        file.WriteLine(data_in + behavior);
                        data_in = "";
                    }
                }
            }
            while (exit_state == false);
        });

        worker.RunWorkerAsync();
    }
    private void bStop_Click(object sender, EventArgs e)
    {
        exit_state = true;
        worker.CancelAsync();
    }

我希望我现在已经更清楚了。 我没有事件编程经验,刚刚开始使用 C#,所以如果可能的话,请尝试在答案中提供一些简单的示例。


一开始使用一个 Winform 就足够了吗?禁用所有复选框,单击启用复选框的按钮并开始读取 tcpstream?如果您因其他原因需要两张表格,请告诉我,但我认为从您的问题中看到的情况不需要这样做。

那么我建议您使用.Net 中的任务库。这是处理多线程的“现代”方法。 BackgroundWorker 有点老派。如果您只能在.Net 2.0 上运行,则必须使用BackgroundWorker,但情况似乎并非如此(示例如下)。

此外,如果您想取消BackgroundWorker操作,这不仅仅是调用CancelAsync();。您还需要处理e.Cancelled flag.

backgroundWorker.WorkerSupportsCancellation = true;

private void CancelBW()
{
   backgroundWorker.CancelAsync();
}

private void backgroundWorker_DoWork += ((sender, args)
{
    //Handle the cancellation (in your case do this in your loop for sure)
    if (e.Cancelled) //Flag is true if someone call backgroundWorker.CancelAsync();
       return;

    //Do your stuff.
});

没有通用的方法可以直接取消backgroundWorker 手术。你总是需要处理这个问题。

现在让我们将您的代码更改为现代 TAP 模式并制作一些您想要的东西。

private void MyForm : Form
{
   private CancellationTokenSource ct;

   public MyForm()
   {
      InitializeComponent();

      checkbox1.Enable = false;
      //Disable all checkboxes here.

      ct = new CancellationTokenSource();
   }

   //Event if someone click your start button
   private void buttonStart_Click(object sender, EventArgs e)
   {
      //Enable all checkboxes here

      //This will be called if we get some progress from tcp
      var progress = new Progress<string>(value =>
      {
          //check the behaviour of the checkboxes and write to file
          file.WriteLine(value + behavior);           
      });

      Task.Factory.StartNew(() => ListenToTcp(ct, progress as IProgress<string)); //starts the tcp listening async
   }

   //Event if someone click your stop button
   private void buttonStop_Click(object sender, EventArgs e)
   {
      ct.Cancel();
      //Disable all checkboxes (better make a method for this :D)
   }

   private void ListenToTcp(CancellationToken ct, IProgess<string> progress)
   {
       do
       {
          if (ct.IsCancellationRequested)
            return;

          int temp = data_feed.ReadByte(); //replaced var => temp because var is keyword
          if (temp != -1)
          {
            data_in += (char)temp;

            if (data_in.IndexOf("\r\n") != -1)
            {
               if (progress != null)
                 progress.Report(data_in); //Report the tcp-data to form thread
               data_in = string.empty;                 
            }
        }
        while (exit_state == false);
   }
}

这个片段应该可以解决问题。我没有测试它,所以可能会出现一些语法错误:P,但原理是可行的。

最重要的是你不被允许访问gui 另一个线程中的组件然后是 gui 线程。您尝试访问 您的BackgroundWorker DoWork 中的复选框是不可能的 并抛出异常。

因此,我使用 Progress-Object 来重用我们在 Tcp-Stream 中获得的数据,返回到主线程。在那里我们可以访问复选框,构建字符串并将其写入文件。您可以找到有关 BackgroundWorker 与 Task 以及 Progress 行为的更多信息here http://blog.stephencleary.com/2013/09/taskrun-vs-backgroundworker-round-5.html.

如果您还有任何疑问,请告诉我。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 do while 循环内检查多个 checkbox.checked 状态 的相关文章

随机推荐