Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 应用程序在新线程函数中停止工作_.net_Multithreading_C# 4.0 - Fatal编程技术网

.net 应用程序在新线程函数中停止工作

.net 应用程序在新线程函数中停止工作,.net,multithreading,c#-4.0,.net,Multithreading,C# 4.0,当我使用消息框跟踪程序停止的位置时 在com.CommandText中,它不显示任何内容,并且应用程序挂起(冻结) 如果我不使用线程,同样的函数也能完美工作 这是什么原因 public bool load_complete=false; private void button7_Click(object sender, EventArgs e) { Thread t1 = new Thread(new ThreadStart(load_data)); t1.Start(

当我使用消息框跟踪程序停止的位置时 在
com.CommandText
中,它不显示任何内容,并且应用程序挂起(冻结)

如果我不使用
线程
,同样的函数也能完美工作

这是什么原因

public bool load_complete=false;  

private void button7_Click(object sender, EventArgs e)
{
    Thread t1 = new Thread(new ThreadStart(load_data));  
    t1.Start();
    Thread.Sleep(2000);
    while (load_complete == false) ;
    t1.Abort();
}


public void load_data()
{
    string connectionString = @"Data Source=(LocalDB)\v11.0;AttachDbFilename=" + Application.StartupPath + "\\Database1.mdf;Integrated Security=True;";

    SqlConnection conn = new SqlConnection(connectionString);
    conn.Open();
    MessageBox.Show("open");
    SqlCommand com = new SqlCommand();
    try
    {
        com.Connection = conn; 
        DataSet ds = new DataSet(); 
        DataTable dt = new DataTable(); 
       
        SqlDataAdapter da = new SqlDataAdapter(); 
        com.CommandText = "select username,password from login where username ='" + textBox1.Text + "'"; 
        da.SelectCommand = com;
        da.Fill(dt);
        dataGridView1.DataSource = dt; 

        username = (string)this.dataGridView1.Rows[0].Cells[0].Value;
        pass = (string)this.dataGridView1.Rows[0].Cells[1].Value;
        load_complete = true;
        
    }
    catch (Exception  ex){
        MessageBox.Show(ex.Message);
    }
}





          

简短版本:您正在阻止将处理消息框显示的UI线程,不要阻止UI线程


较长版本:

上面列出的代码有许多问题。 让我们从显而易见的事情开始:

一,

您的
标志
没有标记,编译器优化可能假定由单个线程访问,在这种情况下,您的代码将永远卡在UI中。如果不是因为代码中的许多其他问题,我建议在这里使用volatile


二,

你正在阻止UI线程,因此任何2秒的用户交互,这是CS101和以后的一个大禁忌,请考虑使用任务和异步/等待来保持UI不可中断。对仍将使用SqlDataAdapter的代码进行最小更改需要:

a) 将按钮处理程序标记为async并等待您需要的任何信息:

private async void button7_Click(object sender, EventArgs e)
{
    await load_data();  
    // more UI code is free to go here
}
b) 在线程池上异步运行
load_data
,并将任务对象返回给调用者:

public Task load_data()
{
     return Task.Run( () => 
     {
         // paste your old load_data code here verbatim
     });
}

三,

t1.Abort()


无法想象那根线对你做了什么,所以你想冷血地打断它。当线程到达您所通过的函数的末尾时,将终止,绝对不需要在这里进行人工流产,如果您下次需要等待线程,请考虑方法

短版本:您正在阻塞将处理消息框显示的UI线程,不要阻塞UI线程


较长版本:

上面列出的代码有许多问题。 让我们从显而易见的事情开始:

一,

您的
标志
没有标记,编译器优化可能假定由单个线程访问,在这种情况下,您的代码将永远卡在UI中。如果不是因为代码中的许多其他问题,我建议在这里使用volatile


二,

你正在阻止UI线程,因此任何2秒的用户交互,这是CS101和以后的一个大禁忌,请考虑使用任务和异步/等待来保持UI不可中断。对仍将使用SqlDataAdapter的代码进行最小更改需要:

a) 将按钮处理程序标记为async并等待您需要的任何信息:

private async void button7_Click(object sender, EventArgs e)
{
    await load_data();  
    // more UI code is free to go here
}
b) 在线程池上异步运行
load_data
,并将任务对象返回给调用者:

public Task load_data()
{
     return Task.Run( () => 
     {
         // paste your old load_data code here verbatim
     });
}

三,

t1.Abort()


无法想象那根线对你做了什么,所以你想冷血地打断它。当线程到达您所通过的函数的末尾时,将终止,绝对不需要在这里进行人工流产,如果您需要等待下一次线程,请考虑方法

另一个选项是使用后台工作人员,正如它所说的,使用后台线程,它不会占用您的主UI线程。当流程完成时,它已经附带了事件

您只需将BackgroundWorker从工具箱拖到表单中

注意:在LoadData方法中,您无法访问任何表单元素,因此必须取出MessageBox。您可以在BackgroundWorker完成的事件处理程序中引用表单元素

    private void button7_Click(object sender, EventArgs e)
    {
          MyWorker.RunWorkerAsync();
    }

    private void MyWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        LoadData();
    }
    private void MyWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error == null)
        {
            string username = (string)this.dataGridView1.Rows[0].Cells[0].Value;
            string pass = (string)this.dataGridView1.Rows[0].Cells[1].Value;
        }
        else
        {
            MessageBox.Show("Houston we have a problem");
        }

    }
    private void LoadData()
    {
        // Load your datagridview
    }

另一个选择是使用BackgroundWorker,正如它所说的,它使用一个不会占用主UI线程的后台线程。当流程完成时,它已经附带了事件

您只需将BackgroundWorker从工具箱拖到表单中

注意:在LoadData方法中,您无法访问任何表单元素,因此必须取出MessageBox。您可以在BackgroundWorker完成的事件处理程序中引用表单元素

    private void button7_Click(object sender, EventArgs e)
    {
          MyWorker.RunWorkerAsync();
    }

    private void MyWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        LoadData();
    }
    private void MyWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error == null)
        {
            string username = (string)this.dataGridView1.Rows[0].Cells[0].Value;
            string pass = (string)this.dataGridView1.Rows[0].Cells[1].Value;
        }
        else
        {
            MessageBox.Show("Houston we have a problem");
        }

    }
    private void LoadData()
    {
        // Load your datagridview
    }

你能用异步任务代替线程吗?你能用异步任务代替线程吗?我发现错误在textbox控件,因为新线程无法更改或获取主线程中的值,所以我将textbox的值存储到一个字符串veriable中,所以我通过com更改查询cammandtext。CommandText=通过com.CommandText=“选择用户名,密码,从用户名=”“+textBox1.Text+””的登录名中选择用户名,密码";你是对的@oleg我是通过主线程运行的,它阻止了主UI线程现在我在一个新线程中运行它现在它已经完成了我发现错误在textbox控件中,因为新线程无法更改或获取主线程中的值,所以我将textbox的值存储到一个字符串veriable,所以我通过com更改查询cammandtext.CommandText=“从登录名中选择用户名,密码,其中用户名=”“+textBox1.Text+””;通过com.CommandText=“从登录名中选择用户名,密码,其中用户名=”“+username+””;您是对的@oleg我是通过阻止主UI线程的主线程运行的现在我在一个新线程中运行此线程现在它是完美的