2012-04-05 37 views
2

我通过GPS调制解调器使用下面的代码通过COMPORT发送短信如何保持禁用,直到一个线程控制结束

Thread thread = null; 
private void btnsend_Click(object sender, EventArgs e) 
    { 
     if (thread == null) 
     {     
      thread = new Thread(SendSms); 
      thread.IsBackground = true; 
      thread.Start(); 
     } 
    } 
    private void Update(int i) 
    { 
     if(InvokeRequired) 
     { 
      this.BeginInvoke(new Action<int>(Update), new Object[] {i}); 
      return; 
     } 
     using (var sp = new SerialPort("COM6")) 
     { 
      sp.Open(); 
      sp.WriteLine("AT" + Environment.NewLine); 
      sp.WriteLine("AT+CMGF=1" + Environment.NewLine); 
      sp.WriteLine("AT+CMGS=\"" + dt2.Rows[i]["PhoneNo"] + "\"" + Environment.NewLine); 
      sp.WriteLine(tbsms.Text + (char)26); 
      if (sp.BytesToRead > 0) 
      { 
       tbsentto.Text = i + 1 + " of " + dt2.Rows.Count; 
      } 
     } 
    } 
    private void SendSms() 
    { 
     for(int i = 0; i < dt2.Rows.Count; i++) 
     { 
      Update(i); 
      Thread.Sleep(5000); 
     } 
     thread = null; 
    } 

我的问题是:我怎么能保持btnsend禁用,直到我的线程是进程,以便用户无法按btnsend向其他收件人发送短信

+0

您可以检查[Thread.IsAlive(http://msdn.microsoft.com/ru-ru/library/system.threading.thread.isalive.aspx) – JleruOHeP 2012-04-05 07:06:14

+0

你需要一个“线程完成“事件。 BackgroundWorker有一个。 – 2012-04-05 08:05:39

回答

3

我在我自己的项目中有一个类似的问题。

我去解决方案如下:

当我创建的后台工作人员的表上的每个按钮给我分配他们的DoWork和RunWorkerCompleted工作线程。

然后,在单击按钮时触发的线程中,我还包含一个检查以确保没有工作线程已经运行(包括按钮本身触发的线程)。

所以我的代码是这样的:

private void XYZ_button_Click(object sender, EventArgs e) 
{ 
    /* Check no background workers are already running */ 
    if ((XYZ_backgroundworker.IsBusy != true) && 
     (PQR_backgroundworker.IsBusy != true)) /* etc, etc for any other background 
     workers you might have */ 
    { 
     XYZ.RunWorkerAsync(); 
    } 
} 

private void XYZ_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    if (e.Error != null) MessageBox.Show("Error: " + e.Error.Message); 
    else if (e.Cancelled == true) MessageBox.Show("Canceled!"); 
} 

private void XYZ_DoWork(object sender, DoWorkEventArgs e) 
{ 
    //Your code here 
} 

我假设你知道如何创建背景的工人,但是,如果没有,你可以在表单设计页面上的工具箱中找到它们。你只需从列表中选择它们,点击你想要分配的按钮,瞧!然后,您只需转到后台工作程序的events属性并分配适当的工作线程即可。

在您的具体情况下,您需要做的是创建后台工作线程并将btnsend_Click的内容移至DoWork线程。然后按照我上面使用的格式。

希望这有助于:)

+0

感谢GeorgePotter,但即使使用您的方法也无法解决我的问题。因为我的真实编码有点大,所以我正在编辑一个相同编码的例子,希望能够解决我的问题。如果例子解决了,我的问题也将得到解决。当我在我上面提到的编码即时按下button1得到这个错误。跨线程操作无效:从其创建的线程以外的线程访问控件'textBox1'。 – kashif 2012-04-05 15:49:43

+0

好的,首先你进入了Form Design选项卡的bgw线程的属性,并转到events属性(小闪电图标)并正确地分配线程? 我只是要重新创建您的示例代码并为自己测试它,看看我是否可以复制您的问题。 – GeorgePotter 2012-04-05 16:10:27

+0

我已经复制了您的代码,但无法获得显示的相同错误。我无法在文本框中显示任何内容,但是您的错误未被复制。 不幸的是,我几乎要离开我的电脑休假几天,所以我可以建议您按照我的建议实施其余代码,并使用messageboxes来显示值。如果你能得到这一点,那么你应该能够在其他地方的文本框中找到解决问题的办法。 此外,还有一些很好的背景工作者教程可能会有所帮助。 – GeorgePotter 2012-04-05 16:22:40

1

您可以调用一个函数,在线程的操作结束时启用该按钮。这是一个简单的方法。但是如果你想更一般地处理这个问题,你可以在Thread类上编写一个包装器,或者从Thread类派生一个新的类。在新类中,您可以创建在线程完成动作结束时触发的事件。

更新:(后汉斯帕桑特提醒我)

您可以使用BackGroundWorker。它和我上面解释的一样。在活动完成后注册事件WorkerCompleted,它将被触发。这是一个小的example

1

,我发现我的问题与GeorgePotter的帮助下解决方案。非常感谢

private void btnsend_Click(object sender, EventArgs e) 
    { 
     foreach (Control c in Controls) 
     { 
      c.Enabled = false; 
     } 
     if (bgw.IsBusy == false) 
     { 
      bgw.RunWorkerAsync(); 
     } 
    } 
    private void Update(int i) 
    { 
     if (InvokeRequired) 
     { 
      this.BeginInvoke(new Action<int>(Update), new Object[] { i }); 
      return; 
     } 
     using (var sp = new SerialPort(cbcomport.Text)) 
     { 
      sp.Open(); 
      sp.WriteLine("AT" + Environment.NewLine); 
      sp.WriteLine("AT+CMGF=1" + Environment.NewLine); 
      sp.WriteLine("AT+CMGS=\"" + dt.Rows[i]["PhoneNo"] + "\"" + Environment.NewLine); 
      sp.WriteLine(tbsms.Text + (char)26); 
      if (sp.BytesToRead > 0) 
      { 
       tbsentto.Text = i + 1 + " of " + dt.Rows.Count; 
      } 
     } 
    }   
    private void bgw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     for (int i = 0; i < dt.Rows.Count; i++) 
     { 
      Update(i); 
      Thread.Sleep(5000); 
     } 
    } 
    private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     foreach (Control c in Controls) 
     { 
      c.Enabled = true; 
     } 
    } 
相关问题