4

we have somewhere in a deep abstraction assembly a WCF behavior that reads data from the OperationContext.Current, when this code is executed from within a Task, the OperationContext.Current is empty, is it possible to solve this inside the abstraction assembly or will we need to add some code to all consumers of this assembly?

svick
  • 236,525
  • 50
  • 385
  • 514
Tim Mahy
  • 1,319
  • 12
  • 28

3 Answers3

3

Was facing a similar issue. Was calling a service through Task. The following code snippet worked out. The OperationContext.Current was explicitly set by casting the state variable being provided by Task before the call to service is done.

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);
Ravi Sankar Rao
  • 1,050
  • 11
  • 26
2

At the point where you create your Task instance, you should use a closure, like so:

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

You can also call the overload of StartNew which takes a state parameter and pass the OperationContext instance in, casting and using it when needed in the Task, like so:

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

Note that in both cases, the OperationContext will only be good for the life of the operation. The completion of the operation should be dependent on the completion of the Task.

If you are launching a Task that will run after the operation completes, then you should copy the values you need from the OperationContext into another structure and pass those into your Task for processing.

casperOne
  • 73,706
  • 19
  • 184
  • 253
  • yes that I know, but the problem is cannot force the consumer code to not just start a Task and do stuff :) – Tim Mahy Jul 17 '12 at 07:14
  • @TimMahy Then it seems you have to build the context into your abstractions, passing it around where you need it. – casperOne Jul 17 '12 at 11:49
0

Seems the only way is to add something to the CallContext, just like the current Principal is stored...

Tim Mahy
  • 1,319
  • 12
  • 28