在循环中使用TaskFactory.StartNew:状态对象不起作用

时间:2014-11-21 14:07:03

标签: c# task-parallel-library

首先,我初始化searchContext列表:

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; }
}

然后为每个searchContext启动新线程:

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()方法调用外部服务以获取下一个搜索结果页面(按pageNumber)。以下是实施:

 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。

无法理解错误是什么?

1 个答案:

答案 0 :(得分:0)

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

但是,现在我实现了WorkRequest的Clone()扩展方法,它将对象字段按字段复制到新实例中。现在它有效。谢谢大家的参与!