Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.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内部使用的字节[]?_C#_.net_Async Await_Task_Backgroundworker - Fatal编程技术网

C# 如何转换任务<;字节[]>;要在BackgroundWorker内部使用的字节[]?

C# 如何转换任务<;字节[]>;要在BackgroundWorker内部使用的字节[]?,c#,.net,async-await,task,backgroundworker,C#,.net,Async Await,Task,Backgroundworker,我有以下方法: public async Task<byte[]> MyMethod(byte[] my_byte_array) { //modify my_byte_array ... return my_modified_byte_array; } 但随后出现一个错误无法将类型“System.Threading.Tasks.Task”隐式转换为“byte[]”。当我读到有关它的解决方案时,它指示将调用函数更改为asycn。但我不能成为as

我有以下方法:

 public async Task<byte[]> MyMethod(byte[] my_byte_array)
 {
    //modify my_byte_array ...


    return  my_modified_byte_array;
     
 }

但随后出现一个错误无法将类型“System.Threading.Tasks.Task”隐式转换为“byte[]”。当我读到有关它的解决方案时,它指示将调用函数更改为asycn。但我不能成为asycn的后台工作人员。这个问题不能解决吗?从BW转换到其他任务方法将花费我大量时间。

您可以使事件处理程序异步。然后使用
wait
解析该值

private async void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
        
    //somewhere in BW
    byte[] my_new_byte_array = await MyMethod(my_byte_array);

}

如果后台工作人员只工作几秒钟(不是分钟),考虑将完整的后台工作人员转换为异步方法。

如果有点依赖,你的backgroundworker会做什么:是因为计算而使用了大量的处理能力,还是主要是在等待外部进程完成,比如读取数据库、从internet获取项目、编写文件等等

在后面的例子中,您将看到backgroundworker使用了许多方法,这些方法可能也具有异步版本

如果是这样的话,考虑把你的背景工作变成一个异步方法。< /P> 假设您的背景工作如下:

private async void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    // get the input:
    List<string> fileNames = (string)e.Argument;
    List<int> processedProductIds = new List<int>();
    // process the input
    for (int i=0; i<fileNames.Count; ++i)
    {
        var products = ReadProductFile(fileNames[i]);
        var productIds = AddProductsToDatabase(products);
        processedProductIds.AddRange(productIds);

        // report progress
        var percentage = 100.0 * (double)i / (double)fileNames.Count;
        backgroundWorker.ReportProgress(percentage, fileName);
    }

    // return output
    e.Result = processedProductIds;
}
将DoWork更改为异步方法。您不必使用事件来报告进度:

public async Task<List<int>> DoWorkAsync(List<string> fileNames)
{
    List<int> processedProductIds = new List<int>();

    for (int i=0; i<fileNames.Count; ++i)
    {
        var products = await ReadProductFileAsync(fileNames[i]);
        var productIds = await AddProductsToDatabaseAsync(products);
        processedProductIds.AddRange(productIds);

        // report progress
        var percentage = 100.0 * (double)i / (double)fileNames.Count;
        ReportProgress(percentage, fileName);
    }
    return processedProductIds;
}
所有的工作都是由同一条线完成的。不完全是这样,但是wait之后的线程具有相同的上下文,因此它可以像原始线程一样工作。因此,不需要互斥体、invokererequired等

启动backgroundworker的事件处理程序现在也是异步的

this.button1.Clicked += OnButtonStartProcessing_ClickedAsync;

private async void OnButtonStartProcessing_ClickedAsync(object sender, ...)
{
    this.button1.Enabled = false;
    this.progressBar1.Value = 0;
    this.progressBar1.Visible = true;

    List<string> fileNames = this.FetchFilesNamesToProcess();
    List<int> processedIds = await ReadProductFilesAsync(fileNames);
    this.UpdateProcessedIds(processedIds);

    this.progressBar1.Visible = false;
    this.button1.Enabled = true;
}
用法:

return await CalculateAsync(3, 4);
最后:如果你可以做一些有用的事情,而不是等待其他任务完成,那么不要等待:

// Fetch the customer, do not await yet:
Task<int> taskA = FetchCustmer();

// because you didn't await, you can continue:
int b = DoSomethingElse();

// now you need the result for taskA
int a = await TaskA;
return a+b; 
//获取客户,不要等待:
任务taskA=FetchCustmer();
//因为您没有等待,所以可以继续:
int b=DoSomethingElse();
//现在需要taskA的结果
int a=等待任务a;
返回a+b;

这将标记BackgroundWorker为已完成。也许这就是OP需要的,也许不是,但不是马上obvious@Charlieface是的,调用ProgressChanged时出错。当代码在DoWork内调用ReportProgress时,我会遇到此错误:System.InvalidOperationException HResult=0x80131509 Message=此操作已对其调用OperationCompleted,并且进一步的调用是非法的。有什么补救办法吗?Anis的答案看起来很有趣,但与dovid的答案很相似,我不认为把这两种异步风格混为一谈是明智的。您不必转换所有代码来使用它,只需这一个工作流,即此特定
BackgroundWorker
s
DoWork
RunWorkerCompleted
events@pnatk正确的解决方案可能是使任何事件启动后台工作程序
async void
,然后在那里调用
wait
您的
MyMethod(my_byte_array)
。@在我的例子中,Llama BW是连续运行的,需要在每个do while(true)循环中调用MyMethod。一个按钮点击事件启动BW,需要在BW内部执行MyMethod的调用和返回,就像我的问题中一样。dovid的答案对我来说很有效,但我不知道为什么会落选。
BackgroundWorker
之所以被创建,是因为没有语言支持异步代码来轻松编写异步代码。以前可以编写异步代码,现在使用
async
-
wait
编写异步代码要容易得多。顺便说一句,
BackgroundWorker
是IMHO。不能处理异步工作负载只是它的缺点之一。我不知道为什么会得到负票。这对我来说很有效。我没有否决新冠病毒,但看到了它的一些缺点:@Llama如果我没有弄错的话,
BackgroundWorker
无论如何都会创建一个专用的新线程。@dovid实际上
BackgroundWorker
使用一个
ThreadPool
线程。您可以通过在控制台中打印属性
Thread.CurrentThread.IsThreadPoolThread
来确认它。
void UpdateProgress (int percentage, string fileName)
{
    this.progressBar.Value = percentage;
    this.ListBoxFileNames.Items.Add(fileName);
}
this.button1.Clicked += OnButtonStartProcessing_ClickedAsync;

private async void OnButtonStartProcessing_ClickedAsync(object sender, ...)
{
    this.button1.Enabled = false;
    this.progressBar1.Value = 0;
    this.progressBar1.Visible = true;

    List<string> fileNames = this.FetchFilesNamesToProcess();
    List<int> processedIds = await ReadProductFilesAsync(fileNames);
    this.UpdateProcessedIds(processedIds);

    this.progressBar1.Visible = false;
    this.button1.Enabled = true;
}
// Warning, this procedure will take 5 seconds!
private int Calculate(int x, int y) {...}

private async Task<int> CalculateAsync(int x, int y)
{
    await Task.Run( () => this.Calculate(x, y));
}
return await CalculateAsync(3, 4);
// Fetch the customer, do not await yet:
Task<int> taskA = FetchCustmer();

// because you didn't await, you can continue:
int b = DoSomethingElse();

// now you need the result for taskA
int a = await TaskA;
return a+b;