gpt4 book ai didi

c# - Waitform 上的进度条使用在另一个线程上运行的任务卡住

转载 作者:太空宇宙 更新时间:2023-11-03 22:34:01 25 4
gpt4 key购买 nike

我有一个使用 OleDb 从 Excel 工作表获取数据的应用程序。
在表单上,​​我有控件,因此用户可以根据需要过滤数据。
例如,FileSizeUserIDRootpath 等。这非常有效。

最终选择后,用户必须按下“更新”按钮,这样我才能根据他的输入过滤数据。结果将显示在 DataGridView 中。

但是,由于 Excel 工作表上的数据变化很大,我曾经在第二个表单上有一个进度条(Waitform)使 DataGridView 不可见,而UI 上的 ProgressBar 在非 UI 任务(数据收集)期间可见。

我知道我应该使用任务或线程(或 BackGroundWorker)来保持 UI 响应。
尽管如此,它仍然卡住了我的整个应用程序。

//Update Button which uses all the userdefined filters
private async void updateButton_Click(object sender, EventArgs e)
{
WaitBarDatagrid.Visible = true; //Progressbar is called WaitBarDatagrid
WaitBarDatagrid.Style = ProgressBarStyle.Marquee;
WaitBarDatagrid.MarqueeAnimationSpeed = 30;

dataGridView1.Visible = false;
await Task.Run(() => QueryToExcel());
dataGridView1.DataSource = FileInfos;
WaitBarDatagrid.Visible = false;
dataGridView1.Visible = true;
}

private void QueryToExcel()
{
this.Invoke((MethodInvoker)delegate ()
{
string fSize;
if (FileSizeComboBox.Text == "All Data")
{ fSize = "0"; }
else if (FileSizeComboBox.Text == "> 1 MB")
{ fSize = "1000"; } // 1MB = 1000kB
else if (FileSizeComboBox.Text == "> 10 MB")
{ fSize = "10000"; } // 10MB = 10.000kB
else if (FileSizeComboBox.Text == "> 100 MB")
{ fSize = "100000"; } // 100MB = 100.000kB
else if (FileSizeComboBox.Text == "> 1 GB")
{ fSize = "1000000"; } // 1 GB = 1000.000 kB
else
fSize = "0";

// The following ensures that all possibilities of User Definition are covered
string user = "";
string size = "";
string sep = ""; //Seperator

if (!string.IsNullOrEmpty(UserTextbox.Text))
{
user = $"[UserID] = '{UserTextbox.Text}'";
sep = "AND";
}

if (!string.IsNullOrEmpty(FileSizeComboBox.Text))
{
size = $"{sep} [File Size] >= {fSize}";
sep = "AND";
}

//Final Where CLAUSE based on User Input
//string command = $@"{user} {size}{sep} [Date] <= {DateBox.Value.ToOADate()}";
string command = $@"{user} {size} {sep} [Date] <= {DateBox.Value.ToOADate()}";

//Call Data from Excel
string connectionString = GetConnectionString(Datapath + RootCombobox.Text);
string query = $@"SELECT * from [FileInfos$] WHERE ({command})";
DataTable dt = new DataTable();

using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
using (OleDbDataAdapter dataAdapter = new OleDbDataAdapter(query, conn))
{
try
{
dataAdapter.Fill(dt);
FileInfos = dt;
}
catch (System.Data.OleDb.OleDbException ex)
{
MessageBox.Show(ex.ToString());
}
}
}
});
}

到目前为止,我还尝试将 Userinputs 的值分配给全局变量,它会在对应的事件中更改。但是,即使调用我的 UI 也会卡住。它从哪里来?

最佳答案

QueryToExcel() 方法应该将工作排队以在 ThreadPool 线程上运行,让 UI 线程继续其自己的工作而不会卡住。
但是您注意到 UI 无论如何都会卡住,并显示:

even with invoke my UI freezes

它从另一个卡住它的线程调用 UI 线程。
在另一个线程上工作就是不使用 UI 线程。如果我们从工作线程调用回 UI 线程,效果就会丢失(或部分丢失,无论如何都很烦人)。

您还使用了 Invoke()而不是 BeginInvoke() .后者是异步执行的:它会立即返回,并且可以在调用的控件繁忙或无法访问/无响应时防止死锁。
无论如何,它不会阻止 UI 有时卡顿。

查看您在此处提供的代码,似乎根本不需要调用 UI 线程:辅助线程只需要一些控件的属性值,然后将 DataTable 分配给字段。

然后可以将所需的值作为参数传递给此方法,将控件的属性分配给某些变量或类的属性(因此更容易理解参数包含的内容)。

worker 方法可以在

private DataTable QueryToExcel(string[] paramArray) 
Or
private DataTable QueryToExcel(SomeClass values)

可以这样称呼:

private async void updateButton_Click(object sender, EventArgs e)
{
var dt = await Task.Run(() => QueryToExcel(values));
Or
dataGridView1.DataSource = await Task.Run(() => QueryToExcel(values));
}

QueryToExcel() 到 Excel 中:

  • 访问 values 参数以设置查询或其他处理。
  • 创建数据库连接并填充数据表/数据集。
  • 处理所有创建的一次性对象(Connection/DataAdapter 等)
  • 返回一个数据表

关于c# - Waitform 上的进度条使用在另一个线程上运行的任务卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56017413/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com