C# WinForms MVP与BackgroundWorker

C# WinForms MVP与BackgroundWorker,c#,winforms,backgroundworker,C#,Winforms,Backgroundworker,我有一个很长的数据查询正在运行,用户需要查看进度 所以我发现,似乎很容易,所以我尝试将其实现到我的应用程序中。在一些测试中,它没有响应,所以在研究时,我发现在使用模型视图演示器设计模式时,您需要进行不同的操作。我在调查的时候遇到过 所以我试着实现它: IView public interface IChecks : IView { void getDataSets(DataSet ds); event EventHandler CheckActive; strin

我有一个很长的数据查询正在运行,用户需要查看进度

所以我发现,似乎很容易,所以我尝试将其实现到我的应用程序中。在一些测试中,它没有响应,所以在研究时,我发现在使用模型视图演示器设计模式时,您需要进行不同的操作。我在调查的时候遇到过

所以我试着实现它:

IView

    public interface IChecks : IView
{
    void getDataSets(DataSet ds);
    event EventHandler CheckActive;
    string sqlQuery { get; set; }
    int checkNumber { get; set; }
    void ShowProgress(int progressPercentage);
    bool isBusy { get; set; }
    event EventHandler StartTimeConsumingJob;
}
private void CheckButton_Click(object sender, EventArgs e)
    {
        //Execute 5 checks, with an number given so the right DataGridViews get filled.
        if (Check1.Checked == true)
        {
            checkNumber = 1;
            sqlQuery = "SELECT DISTINCT e.[BUO] ,e.[Method] ,[EANLocationCode] ,[Customer] FROM [Navision].[dbo].[InventorySales] e WHERE NOT EXISTS (SELECT c.BUO, c.CustomerCode FROM Customers c WHERE c.BUO = e.BUO AND c.CustomerCode = CustomerNo) ORDER BY BUO, Method, LocationCode";
            StartTimeConsumingJob(this, EventArgs.Empty);
        }
    }

    public void getDataSets(DataSet ds)
    {
        if(checkNumber == 1)
        {
            dataGridView1.DataSource = ds.Tables[0];
            Check1Label.Text = ds.Tables[0].Rows.Count.ToString();
            Check1Label.Visible = true;
        }
    }
查看

    public interface IChecks : IView
{
    void getDataSets(DataSet ds);
    event EventHandler CheckActive;
    string sqlQuery { get; set; }
    int checkNumber { get; set; }
    void ShowProgress(int progressPercentage);
    bool isBusy { get; set; }
    event EventHandler StartTimeConsumingJob;
}
private void CheckButton_Click(object sender, EventArgs e)
    {
        //Execute 5 checks, with an number given so the right DataGridViews get filled.
        if (Check1.Checked == true)
        {
            checkNumber = 1;
            sqlQuery = "SELECT DISTINCT e.[BUO] ,e.[Method] ,[EANLocationCode] ,[Customer] FROM [Navision].[dbo].[InventorySales] e WHERE NOT EXISTS (SELECT c.BUO, c.CustomerCode FROM Customers c WHERE c.BUO = e.BUO AND c.CustomerCode = CustomerNo) ORDER BY BUO, Method, LocationCode";
            StartTimeConsumingJob(this, EventArgs.Empty);
        }
    }

    public void getDataSets(DataSet ds)
    {
        if(checkNumber == 1)
        {
            dataGridView1.DataSource = ds.Tables[0];
            Check1Label.Text = ds.Tables[0].Rows.Count.ToString();
            Check1Label.Visible = true;
        }
    }
演示者

        private BackgroundWorker _bw;

    public ChecksPresenter(IChecks view) : base(view)
    {
        View.CheckActive += View_CheckActive;
        View.StartTimeConsumingJob += View_StartTimeConsumingJob;
        _bw = new BackgroundWorker();
        _bw.WorkerReportsProgress = true;
        _bw.WorkerSupportsCancellation = true;
        _bw.DoWork += new DoWorkEventHandler(_bw_DoWork);
        _bw.ProgressChanged += new ProgressChangedEventHandler(_bw_ProgressChanged);
        _bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_bw_Completed);
    }

    void View_CheckActive(object sender, EventArgs e)
    {
        View.getDataSets(CheckModel.dt(View.sqlQuery));
    //This function returns database data.
    }

    public void View_StartTimeConsumingJob(object sender, EventArgs e)
    {
        _bw.RunWorkerAsync();
    }

    private void _bw_DoWork(object sender, DoWorkEventArgs e)
    {
        View.isBusy = true;
        View.getDataSets(CheckModel.dt(View.sqlQuery));
    }

    private void _bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        View.ShowProgress(e.ProgressPercentage);
    }

    private void _bw_Completed(object sender, RunWorkerCompletedEventArgs e)
    {
    }
}
我遗漏了一些东西,因为我确实试着让它先起作用。它不工作也没有响应,只在我按下按钮2次时崩溃(但这是有意义的,因为我没有在CheckButton_click事件中实现if-else)

我的问题:


我错过了什么,它没有回应?这更像是实际的数据库连接没有发生。它可以在没有后台工作程序的情况下工作,但我希望在执行查询时更加清楚。

可能重复“从不写入空的已完成事件处理程序”。务必始终检查e.Error属性,它会告诉您工作线程是否失败。确实如此,您的视图不是线程安全的。可靠地指定文本属性会使其爆炸。分配DataSource属性不会失败,这会以更糟糕的方式失败,但每周只会失败一次。“完成”对于使用辅助结果更新视图也很有用。@HansPassant我用我给出的示例尝试了它,之后我将其置为空。谢谢你的提示,但当我测试它时,我没有发现任何区别。