Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.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# 为什么/如何让BackgroundWorker在没有DoworkerVentargs的情况下工作?_C#_Backgroundworker - Fatal编程技术网

C# 为什么/如何让BackgroundWorker在没有DoworkerVentargs的情况下工作?

C# 为什么/如何让BackgroundWorker在没有DoworkerVentargs的情况下工作?,c#,backgroundworker,C#,Backgroundworker,以下是我在WinForms项目中处理的类的精简版本: class ReportBuilder { private List<Project> projects; private List<Invoice> invoices; private MyAPI apiObject; public ReportBuilder(MyAPI apiAccess, List<Project> selectedProjects){

以下是我在WinForms项目中处理的类的精简版本:

class ReportBuilder {
    private List<Project> projects;
    private List<Invoice> invoices;
    private MyAPI apiObject;

    public ReportBuilder(MyAPI apiAccess, List<Project> selectedProjects){
        this.apiObject = apiAccess;
        this.projects = selectedProjects;
    }

    public void DownloadData(){
        BackgroundWorker workerThread = new BackgroundWorker();
        workerThread.DoWork += (sender, e) => this.retrieveInvoices(this.projects); // yes, the parameter is unnecessary in this case, since the variable is in scope for the method anyway, but I'm doing it for illustrative purposes
        workerThread.RunWorkerCompleted += receiveData;
        workerThread.RunWorkerAsync();
    }

    private void retrieveInvoices(List<Project> filterProjects){
        Notification status;
        if (filterProjects == null){this.invoices = this.apiObject.GetInvoices(out status);}
        else {this.invoices = this.apiObject.GetInvoices(filterProjects, out status);}
    }

    private void receiveData(Object sender, RunWorkerCompletedEventArgs e){
        // display a save file dialog to the user
        // call a method in another class to create a report in csv format
        // save that csv to file

        // ... ideally, this method would to have access to the 'status' Notification object from retrieveInvoices, but it doesn't (unless I make that an instance variable)
    }
}
但是,正如您在上面看到的,我的retrieveInvoices方法的签名与此不匹配。因此,我预计它要么不编译,要么只是在UI线程上运行retrieveInvoices,阻止它,而不是在后台工作程序中。令我惊讶的是,它似乎起了作用,但由于我所看到的BackgroundWorker示例都没有这样做,我仍然认为我一定是做错了什么。但我是吗?为什么?

行:

worker.DoWork += (sender, e) => this.retrieveInvoices(this.projects); 
介绍一个具有参数的委托对象发送方DoWorkEventArgs e,该委托使用参数项目调用方法retrieveInvoices。没有语法不匹配

这相当于:

worker.DoWork += (sender, e) => { this.retrieveInvoices(this.projects); }

要将retrieveInvoices用作实际的事件处理程序,您必须编写:

worker.DoWork += retrieveInvoices;
这将导致不匹配

顺便说一句,BackgroundWorker已经过时了。可以使用Task.Run、async/await和IProgress完成它所做的任何事情以及更多的事情。例如,BGW不能用于组合多个异步操作。使用'async/await'也很容易,例如:

async Task<Report> RunReport(Project[] projects, IProgress<string> progress)
{
    var data= await retrieveInvoices(projects);
    progress.Report("Invoices retrieved");
    var report=await render(data);
    progress.Report("Report rendered");
    await SaveReport(report);
    progress.Report("Report saved");
    return report;
}

//...
Progress<string> progress=new Progress<string>(msg=>statusBar1.Text=msg);

await RunReport(projects);

是的,它确实与此匹配:sender,e=>您可以将e传递给retrieveInvoices方法。那么,sender,e=>bit正在将接下来的内容转换为匿名方法?尽管我对retrieveInvoices?sender的调用没有花括号,但e=>是lambda的语法。它不会转换匿名方法旁边的内容,它是一个方法本身。=>之后的内容是方法的主体OK,我想我现在明白了,谢谢。至于BackgroundWorker不合并多个异步操作的观点,我认为您的意思是添加多个处理程序,例如worker.DoWork+=methodA;worker.DoWork+=methodB将导致处理程序一个接一个地运行,而不是并行运行。不,我的意思是,即使让它工作起来也太复杂了-您必须使用完成处理程序启动下一个BGW,将第一个结果作为状态传递。然后,第二个完成处理程序必须尝试启动第三个完成处理程序,等等。更不用说错误处理了。但在我发布的问题中,只有三个wait someasynchmethod调用一个接一个
worker.DoWork += retrieveInvoices;
async Task<Report> RunReport(Project[] projects, IProgress<string> progress)
{
    var data= await retrieveInvoices(projects);
    progress.Report("Invoices retrieved");
    var report=await render(data);
    progress.Report("Report rendered");
    await SaveReport(report);
    progress.Report("Report saved");
    return report;
}

//...
Progress<string> progress=new Progress<string>(msg=>statusBar1.Text=msg);

await RunReport(projects);