调用 runworkerasync 的事件:
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (textBox1.Text.Length <= 3)
{
_ishouldnteventrytoupdate = true;
return;
}
_ishouldnteventrytoupdate = false;
_updated = false;
backgroundWorker1.RunWorkerAsync();
}
工作函数:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// MessageBox.Show("hallo");
// if (_ishouldnteventrytoupdate) return;
//if (_updated) return;
allArtikels = DatabaseConn.GetAllArtikelsArrayList(false, textBox1.Text);
//backgroundWorker1.ReportProgress(100);
}
DatabaseConn 是一个静态类,这是被调用的函数:
public static ArrayList GetAllArtikelsArrayList(bool showAll,String naamZoeker = "")
{
SetupConnection();
_objConnection.Open();
var allArtikels = new ArrayList();
var strSql = "SELECT ";
if (!showAll)
{
strSql += "TOP 10";
}
strSql+=" HOOFDGROEP.HOOFDGROEP, SUBGROEP.SUBGROEP, Artikels.*" +
" FROM (Artikels LEFT JOIN HOOFDGROEP ON Artikels.HOOFDGROEPID = HOOFDGROEP.ID)" +
" LEFT JOIN SUBGROEP ON Artikels.SUBGROEPID = SUBGROEP.ID WHERE (ArtikelNaam LIKE '%' + @ArtikelNaam + '%');";
var objCommand = new OleDbCommand(strSql, _objConnection);
objCommand.Parameters.Add("@ArtikelNaam", OleDbType.Char).Value = naamZoeker;
try
{
var objReader = objCommand.ExecuteReader();
if (objReader != null && objReader.HasRows)
{
while (objReader.Read())
{
var objArtikel = new Artikel
{
SubGroepId = IntDbTester(objReader["SubgroepId"]),
HoofdGroepId = IntDbTester(objReader["HoofdgroepId"]),
AdviesPrijsIncl = DecimalDbTester(objReader["ArtikelAdviesPrijsIncl"]),
AdviesPrijsExcl = DecimalDbTester(objReader["ArtikelAdviesPrijsExcl"]),
BtwPercentage = IntDbTester(objReader["ArtikelBtwPercentage"]),
Naam = StringDbTester(objReader["ArtikelNaam"]),
OldId = StringDbTester(objReader["ArtikelOldId"]),
Id = IntDbTester(objReader["ArtikelId"]),
Voorraad = DoubleDbTester(objReader["ArtikelVoorraad"])
};
allArtikels.Add(objArtikel);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
_objConnection.Close();
return allArtikels;
IntDbTesters、Stringdbtester 等函数看起来像这样:
public static int IntDbTester(object s)
{
return s == DBNull.Value ? 0 : Convert.ToInt32(s);
}
SetupConnection() 看起来像这样:
private static void SetupConnection()
{
const string strConnection = "Provider=Microsoft.ACE.OLEDB.12.0;" +
"Data Source='Klanten.accdb';" +
"Persist Security Info=False";
_objConnection = new OleDbConnection(strConnection);
}
除了 catch(以前从未调用过,所以我不认为使用 backgroundworker 会突然调用它)在 backgroundworker 中没有一个 UI,但是当我输入超过 3 个时,我的应用程序永远卡住文本框中的字母。
这可能是什么原因造成的?
编辑: 异常(exception)是:
System.dll 中发生了类型为“System.InvalidOperationException”的未处理异常附加信息:Deze BackgroundWorker 已被删除。大致翻译为backgorundworker很忙,不能同时执行多个任务
if ((backgroundWorker1 != null) &&!backgroundWorker1.IsBusy)backgroundWorker1.RunWorkerAsync();
暂时解决了这个问题,但我希望它实际上取消当前的工作并开始一个新的...
最佳答案
我发现您的代码存在一些问题。然而,最大的问题是您正试图从非 UI 线程读取 UI 组件,即
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// MessageBox.Show("hallo");
// if (_ishouldnteventrytoupdate) return;
//if (_updated) return;
allArtikels = DatabaseConn.GetAllArtikelsArrayList(false, textBox1.Text);
//backgroundWorker1.ReportProgress(100);
}
您应该在调用 RunWorkerAsync
时传入您的文本
backgroundWorker1.RunWorkerAsync(textBox1.Text);
...
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
allArtikels = DatabaseConn.GetAllArtikelsArrayList(false, (string)e.Argument);
}
既然您已经揭示了您收到的异常,很明显该问题与在工作人员忙碌时尝试调用 RunWorkerAsync
有关。为了有效地停止/重启工作人员,您需要启用取消支持。例如
private void Search()
{
backgroundWorker1.RunWorkerAsync(textBox1.Text);
}
...
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.Completed += (sender, e) {
if (e.Cancelled) {
// restart background worker
Search();
}
};
...
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy) {
backgroundWorker1.CancelAsync();
} else {
Search();
}
}
假设您在此处追求预先键入行为,每次击键 触发数据库查询并不是一个好主意。一个更好的想法是尝试预测用户何时完成输入,然后然后执行查询 - 这应该会减少访问数据库的次数,这意味着更有效地使用资源和更好的整体用户体验。一种简单而有效的方法是设置一个计时器,每次用户编辑文本时您都会重置该计时器,并且仅在达到计时器超时时才触发查询。
如果您需要在不等待前一个工作人员的情况下启动新查询,那么我建议您使用 TPL而不是 BackgroundWorker
。
private CancellationTokenSource cancellationTokenSource;
...
private void Search()
{
if (this.cancellationTokenSource != null)
this.cancellationTokenSource.Cancel();
// Create a new cancellation token for the new task.
this.cancellationTokenSource = new CancellationTokenSource();
CancellationToken cancellationToken = this.cancellationTokenSource.Token;
// Start the new task.
var text = textBox1.Text;
Task.Run(() =>
{
return DatabaseConn.GetAllArtikelsArrayList(false, text);
}, cancellationToken)
.ContinueWith((t) =>
{
// do something with t.Result if it wasn't cancelled
}, cancellationToken, TaskContinuationOptions.NotOnCancelled, TaskScheduler.FromCurrentSynchronizationContext());
关于c# - BackgroundWorker 崩溃程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24933506/