选择多个复选框.do while循环内的已检查状态

本文关键字:检查 状态 循环 while 复选框 do 选择 | 更新日期: 2023-09-27 18:17:57

我在之前的问题中问过如何"线程化两个窗体以同时使用c# "。
我现在意识到我问得不够明确,而且问错了问题。

这是我的场景:
我有一些数据,我从本地服务器接收,我需要写入一个文件。这个数据正在以我无法控制的恒定时间速率发送。
我想做的是有一个winform的tcp流的初始设置,然后点击一个按钮开始读取tcp流并将其写入文件,同时启动另一个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#,所以如果可能的话,请尽量在答案中提供一些简单的例子。

选择多个复选框.do while循环内的已检查状态

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

那么我建议你使用。net中的任务库。这是处理多线程的"现代"方式。BackgroundWorker有点老派。如果你只能在。net 2.0上运行,你必须使用BackgroundWorker,但似乎不是这样(示例如下)。

如果你想取消一个BackgroundWorker操作,这不仅仅是调用CancelAsync();。您还需要处理e.Cancelled标志。

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-Pattern,并做一些你想要的东西。

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流中获得的数据,返回到主线程。在这里,我们可以访问复选框,构建字符串并将其写入文件。你可以在这里找到更多关于BackgroundWorker vs. Task和Progress行为的信息。

请告诉我还有什么问题。