C# 如何将唯一字符串传递给异步方法?
C# How to pass unique string to async method?
我正在创建多个线程,将不同的数据传递给每个线程。
但是,在 CallAsync 方法中,我有时会收到相同的数据。
为什么输入输出数据不同?
如何正确地将唯一字符串传递给每个线程?
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace NTest
{
class Program
{
static async Task<int> CallAsync(string str)
{
Console.WriteLine("income: {0}", str);
// await ...
return 0;
}
static async void WorkerMainAsync()
{
List<Task> trackedTasks = new List<Task>();
int[] jobs = new int[] { 0,1,2,3,4,5 };
string str;
foreach (int num in jobs)
{
str = num.ToString();
Console.WriteLine("pass: {0}", str);
trackedTasks.Add(Task.Run(() => CallAsync(str)));
}
await Task.WhenAll(trackedTasks);
Console.WriteLine("[*] All jobs finished.");
}
static void Main(string[] args)
{
WorkerMainAsync();
Console.ReadLine();
}
}
}
控制台输出:
pass: 0
pass: 1
pass: 2
income: 1
income: 2
pass: 3
pass: 4
income: 4
income: 4
income: 4
pass: 5
income: 5
[*] All jobs finished.
这与方法是异步的事实没有任何关系。
此行为是因为 lambda 表达式关闭变量,而不是值。所以表达式 () => CallAsync(str)
总是引用相同的 str
变量,最终在所有调用之间共享。
一个简单的解决方法是在循环内声明变量,这样每个 lambda 闭包都有自己的变量:
int[] jobs = new int[] { 0,1,2,3,4,5 };
foreach (int num in jobs)
{
var str = num.ToString();
Console.WriteLine("pass: {0}", str);
trackedTasks.Add(Task.Run(() => CallAsync(str)));
}
await Task.WhenAll(trackedTasks);
我正在创建多个线程,将不同的数据传递给每个线程。 但是,在 CallAsync 方法中,我有时会收到相同的数据。
为什么输入输出数据不同?
如何正确地将唯一字符串传递给每个线程?
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace NTest
{
class Program
{
static async Task<int> CallAsync(string str)
{
Console.WriteLine("income: {0}", str);
// await ...
return 0;
}
static async void WorkerMainAsync()
{
List<Task> trackedTasks = new List<Task>();
int[] jobs = new int[] { 0,1,2,3,4,5 };
string str;
foreach (int num in jobs)
{
str = num.ToString();
Console.WriteLine("pass: {0}", str);
trackedTasks.Add(Task.Run(() => CallAsync(str)));
}
await Task.WhenAll(trackedTasks);
Console.WriteLine("[*] All jobs finished.");
}
static void Main(string[] args)
{
WorkerMainAsync();
Console.ReadLine();
}
}
}
控制台输出:
pass: 0
pass: 1
pass: 2
income: 1
income: 2
pass: 3
pass: 4
income: 4
income: 4
income: 4
pass: 5
income: 5
[*] All jobs finished.
这与方法是异步的事实没有任何关系。
此行为是因为 lambda 表达式关闭变量,而不是值。所以表达式 () => CallAsync(str)
总是引用相同的 str
变量,最终在所有调用之间共享。
一个简单的解决方法是在循环内声明变量,这样每个 lambda 闭包都有自己的变量:
int[] jobs = new int[] { 0,1,2,3,4,5 };
foreach (int num in jobs)
{
var str = num.ToString();
Console.WriteLine("pass: {0}", str);
trackedTasks.Add(Task.Run(() => CallAsync(str)));
}
await Task.WhenAll(trackedTasks);