Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.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
C# 异步&;windows窗体中的多线程_C# - Fatal编程技术网

C# 异步&;windows窗体中的多线程

C# 异步&;windows窗体中的多线程,c#,C#,我正在从数据库中将大约10万行的数据检索到datagridview中。此过程最多需要5-6秒。但是在这几秒钟内,用户无法移动鼠标或单击任何其他按钮。我如何使用aysnc/多线程来实现平滑的用户界面。让我们假设您作为一个用户来完成所有这些处理器密集型工作点击按钮的结果。希望您已经在一个单独的方法中完成了工作,并且正在从单击事件调用该方法。如果您的所有工作都在click事件中,请将其移出到自己的方法中,并从click事件处理程序调用它 现在这仍然是一个单一的线程。我将在这里使用一个单独的线程来解决这

我正在从数据库中将大约10万行的数据检索到datagridview中。此过程最多需要5-6秒。但是在这几秒钟内,用户无法移动鼠标或单击任何其他按钮。我如何使用aysnc/多线程来实现平滑的用户界面。

让我们假设您作为一个用户来完成所有这些处理器密集型工作点击按钮的结果。希望您已经在一个单独的方法中完成了工作,并且正在从单击事件调用该方法。如果您的所有工作都在click事件中,请将其移出到自己的方法中,并从click事件处理程序调用它

现在这仍然是一个单一的线程。我将在这里使用一个单独的线程来解决这个问题,不过您也应该自己研究任务。要使用单独的线程进行艰苦的工作,请编写如下两行代码:

Thread t = new Thread(nameOfTimeConsumingMethod);
t.Start();
那就行了。如果需要将输出写入(比如)textBox1,则不能直接从新线程写入(没有跨线程调用)。但是你仍然可以像这样很容易地间接地写信给那个盒子

BeginInvoke(new Action(()=>textBox1.text = "Hello world!"));

查看任务库和async,C#中有整整一部分用于实现这一点

基本上,你会得到像

var records = await GetRecordsFromDatabase();
MyDataGridView.ItemSource = records;

private Task<IEnumerable<Record>> GetRecordsFromDatabase(){
    return Task.Run(() => {
          //do stuff the return IEnumerable<Records>
    });
}
var records=wait GetRecordsFromDatabase();
MyDataGridView.ItemSource=记录;
私有任务GetRecordsFromDatabase(){
返回任务。运行(()=>{
//将返回的内容设置为不可数
});
}
请注意,虽然可以使用线程,但任务在C#中是一个更好的异步支持选项

编辑-大多数数据库应该支持一些异步操作。在这种情况下,您可能会使用一种异步方法将数据库中的内容转换为所需的格式。您可能还希望遵循将自己的方法标记为异步的约定。像

private async Task<IEnumerable<Record>> GetRecordsFromDatabaseAsync(){
    var dbRecords = await Database.GetRecordsAsync();

    //transform the database records and return them
}
专用异步任务GetRecordsFromDatabaseAsync(){
var dbRecords=await Database.GetRecordsAsync();
//转换数据库记录并返回它们
}

如上所述。

创建一个新线程来完成这项工作。因为多线程总是增加复杂性,并且可能是许多难以跟踪的bug的来源:它值得吗?等待5-6秒对我来说似乎不算什么…@Udontknow显然你没有太多的经验来处理那些在工作时会冻结的应用程序。这是一种糟糕的用户体验。@我知道,我认为它几乎总是值得的。除了在普通的单元测试中,我总是让UI线程扮演导体和事件处理程序,而几乎没有其他功能。对于一个简单的线程练习,在一个单独的线程上运行它实际上只需要两到三行额外的代码。特别是在C#中,它可能是所有语言中最好的异步支持,没有理由不正确地执行它。谢谢你,伙计,我试试这个,你不应该使用
任务。在这里运行
;他在做IO工作,而不是CPU限制的工作,所以操作本身就是异步的。你完全正确。然而,我很好奇——这是在方法级别发生的,还是仅仅假设数据库支持do stuff区域中的异步操作?这与数据库支持的内容无关,而是关于您用来连接到该数据库的客户端。交互本质上已经是异步的。有些客户端通过阻止执行直到异步操作完成来异步隐藏这些操作,有些客户端在异步操作中公开操作,有些客户端同时公开这两个操作。我指的是支持异步的数据库客户端,而不是数据库本身。如果数据库客户机不提供异步方法,而是在读取时阻塞,那么仅将该方法声明为Task是不起作用的。相反,编译器警告将告诉您操作将同步进行。由于这将在UI线程上,OP将继续存在问题。无论如何,我的看法是——如果我在这方面不正确,我很想知道原因。大多数数据库客户端实际上都支持某种形式的异步操作。找到一个没有的是很不寻常的。