2013-05-31 22 views
1

创建我新的线程和我收到此错误跨线程操作无效:控制“comboBoxLocation”从比它是在

跨线程操作无效的线程以外的线程访问:控制'comboBoxLocation'从其创建线程以外的线程访问 。

我不知道我是否正确创建这个线程,但每次它给我的错误。有谁知道如何解决这个问题。我已经尝试过了:

this.Invoke(new MethodInvoker(delegate() 
{ 
    da.SelectCommand.Parameters.AddWithValue("@QueueID", comboBoxLocation.SelectedValue.ToString()); 
})); 

而且我仍然遇到那个错误。

string branch; 
SpeechSynthesizer reader = new SpeechSynthesizer(); 
Thread t; 
bool flag; 

//SqlDataReader dr2; 
public Main() 
{ 
    InitializeComponent(); 
} 

private void btnStart_Click(object sender, EventArgs e) 
{ 
    lblStatus.Text = "Started!"; 
    btnStop.Enabled = true; 
    btnStart.Enabled = false; 
    t = new Thread(Begin); //calls Begin method 
    t.Name = "Queue"; //thread name 
    t.Start(); //Starts thread 
    flag = false; 
    branch = comboBoxLocation.SelectedValue.ToString(); 
} 

private void btnStop_Click(object sender, EventArgs e) 
{ 
    lblStatus.Text = "Voice Application Termintated!"; 
    btnStart.Enabled = true; 
    btnStop.Enabled = false; 
    t.Abort(); //Kills Thread 
    flag = true; 
}  

//Began method 
public void Begin() 
{ 
    double announce; 
    double announceID; 

    string Stringannounce; 
    string ticketNum, station, id, displaynum; 
    string speak; 

    try 
    { 
     using (SqlConnection connStr = new SqlConnection(ConfigurationManager.ConnectionStrings["AnnounceConnString"].ConnectionString)) 
     { 
      while (true) 
      { 
       //Selects Last record written to tblAnnounce 
       SqlCommand sqlcommandStart = new SqlCommand("SELECT id, AnnounceID, AddDate FROM tblAnnounce ORDER by AddDate ASC", connStr); 
       connStr.Open(); 

       SqlDataReader dr = sqlcommandStart.ExecuteReader(); 

       if (dr.HasRows) 
       { 
        while (dr.Read()) 
        { 
         Stringannounce = dr["AnnounceID"].ToString(); 
         announceID = Convert.ToDouble(Stringannounce); 


         SqlDataAdapter da = new SqlDataAdapter("SELECT TOP 1 id, qdate, ticket_number, QueueID, received, displaynum, station, transcodevoiced FROM vwAnnounce WHERE QueueID = @QueueID ORDER by received ASC", connStr); 
         //da.SelectCommand.CommandType = CommandType.StoredProcedure; 

         DataSet ds = new DataSet(); 
    *****************da.SelectCommand.Parameters.AddWithValue("@QueueID", comboBoxLocation.SelectedValue.ToString());***** //ERROR HERE 
         da.Fill(ds); 

         DataTable dt = new DataTable(); 
         dt = ds.Tables[0]; 


         foreach (DataRow dr2 in dt.Rows) 
         { 
          id = dr2["id"].ToString(); 
          announce = Convert.ToDouble(id); 
          ticketNum = dr2["ticket_number"].ToString(); 
          station = dr2["station"].ToString(); 
          //transcodevoiced = dr2["transcodevoiced"].ToString(); 
          displaynum = dr2["displaynum"].ToString(); 
          SplitString splitter = new SplitString(displaynum); 
          splitter.Split(); 

          if (announceID == announce) 
          { 
           // Set a value for the speaking rate. 
           reader.Rate = -4; 
           // Set the volume of the SpeechSynthesizer's ouput. 
           reader.Volume = 85; 
           //String that will be spoken 
           speak = "Now, " + displaynum + ", at #" + station; 

           //The problem with the Speak() function is that it is not threaded, so we use SpeakAsync(). It means that you cannot perform any other function in your windows form until the "reader" object has completed the speech. 
           reader.SpeakAsync(speak); 
           //Pauses system for 1 seconds after voice completion 
           Thread.Sleep(3000); 

           //Deletes record from Database table tblAnnounce 
           SqlCommand delete = new SqlCommand("DELETE FROM tblAnnounce WHERE AnnounceID = @announceID ", connStr); 
           delete.Parameters.AddWithValue("@announceID", announceID); 
           delete.ExecuteNonQuery(); 
           reader.Resume(); 
          } 
         }            
        } 
        connStr.Close(); 
       }      
       dr.Close(); 
      } 
     } 
    } 
    catch(Exception ex) 
    { 
     string exception = ex.Message; 
    } 
} 
+0

'comboBoxLocation'是如何创建的,是在设计器中创建的,还是在运行时动态添加的? –

+0

如果您对解释感兴趣,这是一个很好的资源。如何:线程安全调用Windows窗体控件http://msdn.microsoft.com/en-us/library/ms171728.aspx –

+0

旁注:*不*使用'Thread.Abort()'杀死一个线程。使用某种形式的同步来告诉它停止。 [见本文档](http://msdn.microsoft.com/en-us/library/dd537607.aspx)为例。 –

回答

1

理清你的问题,Invoke应该把以低于行:

comboBoxLocation.Invoke(
new Action(() => branch = comboBoxLocation.SelectedValue.ToString()); 

希望这有助于。

+0

WOW。非常好 –

0

您正在通过窗体而不是控件调用。

使用此:

comboBoxLocation.Invoke(new MethodInvoker(delegate() 
{ 
    da.SelectCommand.Parameters.AddWithValue("@QueueID", comboBoxLocation.SelectedValue.ToString()); 
})); 

通过代替控制调用。

这是关于Microsoft线程安全调用的一个很好的资源。

http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx

为了提高在你的代码,你也可以检查,看看是否需要调用或没有这样做之前。示例:

if (comboBoxLocation.InvokeRequired) 
{ 
    comboBoxLocation.Invoke(
      (MethodInvoker) 
       delegate { 
        da.SelectCommand.Parameters.AddWithValue("@QueueID", comboBoxLocation.SelectedValue.ToString()); 
}); 
else 
{ 
    da.SelectCommand.Parameters.AddWithValue("@QueueID", comboBoxLocation.SelectedValue.ToString()); 
} 
+0

只要表单和控件是在同一个线程上创建的,那么用于“调用”的应该没关系。 – hvd

+0

他的代码不显示组合框的创建位置。我可以认为它是相同的,基于对InitializeComponents的调用,这意味着他可能使用了设计器 - 但我不会假设。 – Chris

+0

是我的线程在这里使用得当吗? – Apollo

相关问题