在任务并行库中保留OperationContext

4
我们在一个深层次的抽象程序集中有一个WCF行为,它从OperationContext.Current中读取数据。当这段代码从任务中执行时,OperationContext.Current为空。我们能否在抽象程序集内部解决这个问题,还是需要向所有使用该程序集的消费者添加一些代码?请注意,保留HTML标记。

谁启动了Task?消费者吗?在启动Task之前,抽象程序集中是否执行了任何代码? - svick
不,那就是问题所在,消费者启动任务 :( - Tim Mahy
3个回答

3

我曾遇到类似的问题。通过Task调用服务。 下面这段代码可以解决该问题。在调用服务之前,通过将Task提供的state变量强制转换来明确设置OperationContext.Current

Task<int> taskContactsCount = Task.Factory.StartNew<int>((state) =>
        {
            int count = 0;
            try
            {
                OperationContext.Current = (OperationContext)state;
                TestServiceClient testServiceProxy = new TestServiceClient();
                var count = testServiceProxy.GetCount();
            }
            catch (Exception ex)
            {
            }
            return contactsCount;
        }, OperationContext.Current);

2
在创建任务实例的时候,你应该使用一个闭包,像这样:
// The operation context.
OperationContext oc = OperationContext.Current;

Task t = Task.Factory.StartNew(() => {
    // Do something with context here, it will be valid for
    // the life of the operation.
};

您还可以调用带有state参数的StartNew重载,并将OperationContext实例传递进去,在Task中需要时进行转换和使用,例如:
Task t = Task.Factory.StartNew(s => {
    // s is an object, so need to cast here.
    var oc = (OperationContext) c;

    // Work with the OperationContext.
},
// Note, this is passed to the delegate through the 's' parameter.
OperationContext.Current);

请注意,在这两种情况下,OperationContext 仅在操作的生命周期内有效。操作的完成应该取决于 Task 的完成。
如果您启动的 Task 将在操作完成后运行,则应将所需的值从 OperationContext 复制到另一个结构中,并将 它们 传递给您的 Task 进行处理。

是的,我知道,但问题在于无法强制消费者代码不仅启动任务并执行操作 :) - Tim Mahy
@TimMahy 那么看来你必须将上下文构建到你的抽象中,在需要它的地方传递它。 - casperOne

0

看起来唯一的方法是向CallContext添加一些内容,就像当前的Principal被存储一样...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接