【问题标题】:Sending bulk messages using serial port communication使用串口通信发送批量消息
【发布时间】:2012-08-14 10:25:09
【问题描述】:

我可以通过写作从我的应用程序中发送消息

port.WriteLine("AT+CMGS=\"" + m.Groups[2].Value + "\"");
port.Write(txt_msgbox.Text + char.ConvertFromUtf32(26));

这很好。但现在我想向一组号码发送批量消息。我有这个循环向一组数字发送消息:

foreach (ListViewItem item in bufferedListView1.Items)
{
    string lname = bufferedListView1.Items[i].Text;
    string lno = bufferedListView1.Items[i].SubItems[1].Text;
    string gname = bufferedListView1.Items[i].SubItems[2].Text;
    string line = lname + "@" + lno + "@" + gname;
    if (gname.Contains(sgroup))
    {
        var m = Regex.Match(line, @"([\w]+)@([+\d]+)@([\w]+)");
        if (m.Success)
        {
            port.WriteLine("AT+CMGS=\"" + m.Groups[2].Value + "\"");
            port.Write(txt_msgbox.Text + char.ConvertFromUtf32(26));
            Thread.Sleep(4000);
        }
        sno++;
    }
    i++;
}

这也很有效。但问题出在 UI 上,在相当长的一段时间内变得反应迟钝。有什么更好的方法吗?

【问题讨论】:

    标签: c# multithreading sms serial-port


    【解决方案1】:

    使用BackgroundWorker - 它们非常易于使用并以封装的方式管理线程。此类的好处是,如果您希望能够取消进程,它支持取消,并且它支持报告进度,我将在这里展示这两者。最后,这个类的好处是,当它报告进度时,它会正确切换线程,确保您不会在单独的线程上写入 UX - 但 DoWork 事件处理程序中的代码仍然在单独的线程上正确管理线程。

    您将执行以下操作。

    // in this example this is scoped to the class, but just scope it appropriately
    private BackgroundWorker worker = new BackgroundWorker();
    
    ......
    
    // because I don't really know anything about how your program is structured I'm not sure
    // where you want to place all of the definitions OR where you want to place RunWorkerAsync
    // but you want the definitions to happen ONCE and the RunWorkerAsync to be where the USER
    // initiates it
    
    // this will allow you to consume the ProgressChanged event
    worker.WorkerReportsProgress = true;
    
    // this will allow you to set the CancellationPending property
    worker.WorkerSupportsCancellation = true;
    
    worker.DoWork += (o, args) =>
    {
        foreach (ListViewItem item in bufferedListView1.Items) 
        { 
            string lname = bufferedListView1.Items[i].Text; 
            string lno = bufferedListView1.Items[i].SubItems[1].Text; 
            string gname = bufferedListView1.Items[i].SubItems[2].Text; 
            string line = lname + "@" + lno + "@" + gname; 
            if (gname.Contains(sgroup)) 
            { 
                var m = Regex.Match(line, @"([\w]+)@([+\d]+)@([\w]+)"); 
                if (m.Success) 
                { 
                    port.WriteLine("AT+CMGS=\"" + m.Groups[2].Value + "\""); 
                    port.Write(txt_msgbox.Text + char.ConvertFromUtf32(26)); 
                    Thread.Sleep(4000); 
                } 
                sno++; 
            } 
            i++; 
        }
    }
    
    worker.ProgressChanged += (s, args) =>
    {
        // set some progress here, the ProgressChangedEventArgs inherently supports an integer
        // progress via the ProgressPercentage property
    }
    
    worker.RunWorkerCompleted += (s, args) =>
    {
        // with the RunWorkerCompletedEventArgs class you can check for errors via Error, did
        // cancellation occur via Cancelled, and you can even send a complex result via the Result
        // property - whatever you need
    }
    
    // this starts the work in the DoWork event handler
    worker.RunWorkerAsync();
    

    这是微软关于此事的文档的link

    【讨论】:

    • worker.DoWork 中使用 bufferedListView1.Items 会导致此异常 - Cross-thread operation not valid: Control 'bufferedListView1' accessed from a thread other than the thread it was created on.
    • @Cdeez - 是的,你是对的,我没有注意到那里的循环正确。您需要将ListViewItemCollection 转换为可以传递给args 的东西,比如Tuple,因为这与ListViewItem 非常相似,然后将调用更改为RunWorkerAsync 以通过在那个变量中。
    • @Cdeez - 另外,一旦您将代码转换并正常工作,请编辑我的问题并为社区发布更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-24
    • 2013-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多