c# - BackgroundWorker 崩溃程序

标签 c# database backgroundworker freeze

调用 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/

相关文章:

c# - 如何退出 C# 机器人框架中的对话框?

c# - 通过 linq 从 xml 检索数据时出现问题

java - 尝试通过JDBC在MySQL中存储SecretKey、加密密码

c# - WinForms 应用程序 w/BackgroundWorker 和类对象事件

c# - GUI在获取数据时未响应

c# - 如何使用 DocumentDb 从 HttpTrigger 路由中提取分区键?

c# - Automapper 未将 IEnumerable<T> 映射到 Viewmodel 中的 IEnumerable<T>

sql-server - SQL : Distinct Medications to Columns Using Pivot

ruby-on-rails - 恢复 mongodb 数据库 .bson 和 .json 文件

python - 如何在 Linux 中重定向屏幕后台进程的所有输出?