使用 TaskFactory.StartNew 内部循环:状态对象不起作用

本文关键字:状态 对象 不起作用 循环 TaskFactory StartNew 内部 使用 | 更新日期: 2023-09-27 18:31:19

首先我初始化搜索上下文列表:

var searchContexts = new List<SearchContext>();
for (byte pageNumber = 1; pageNumber < 6; pageNumber++)
{
    var searchContext = GetSearchContext(context, vendor, workRequest, pageNumber);
    searchContexts.Add(searchContext);
}     

其中 SearchContext 定义如下:

public class SamoSearchContext
{
    public WorkRequest WorkRequest 
    { get; set; }
    public Vendor Vendor 
    { get; set; }
    public WorkResponse WorkResponse
    { get; set; }
    public byte PageNumber 
    { get; set; }
}

然后为每个搜索上下文启动新线程:

var tasks = new Task[taskCount];         
var taskScheduler = TaskScheduler.Default;
var index = 0;
foreach (var searchContext in searchContexts)
{
    var ssc = searchContext;
    tasks[index] = Task.Factory.StartNew((obj) => SendSearchRequest(ssc, token),
                ssc, token, TaskCreationOptions.AttachedToParent, taskScheduler);
    index++;
 }

SendSearchRequest() 方法调用外部服务以获取下一个搜索结果页面(按页码)。以下是实现:

 private void SendSearchRequest(SamoSearchContext context, CancellationToken token)
    {
        if (token.IsCancellationRequested)
            return;
        var workRequest = context.WorkRequest;
        workRequest.@params.PRICE_PAGE = context.PageNumber;
        context.WorkResponse = ServiceClient.GetWorkResponse<WorkRequest, WorkResponse>(ServiceOperations.GetPrice, workRequest, context.Vendor.UniformCode, context.Vendor.ID);

}

但是在循环执行后读取日志,我看到 pageNumber 总是 = 4。

不明白出了什么问题?

使用 TaskFactory.StartNew 内部循环:状态对象不起作用

问题是当我创建 SearchContext 列表时,我不谨慎地使用了 copy workRequest by 引用 (newSearchContext.WorkRequest = workRequest)。因此,列表中的所有搜索上下文都引用了一个 workRequest 实例。然后,在 SendRequest() 中,每次我更改PRICE_PAGE这个实例的字段时。所以它是一样的,有点奇怪,它总是 = 4,但不是从 1 到 5 的随机数。

但是,尽管如此,现在我为 WorkRequest 实现了 Clone() 扩展方法,该方法将对象逐个字段复制到新实例中。现在它起作用了。感谢大家的参与!