我建立了一套ASP.Net托管必须使用旧库,它在很大程度上取决于HttpContext.Current的WebAPI服务。我无法确保这方面是pserved在所有参与的异步调用的方法$ P $。我曾尝试在以下code几个变化与计谋/ Task.Wait和TaskScheduler.FromCurrentSynchronizationContext()。
I am building a set of ASP.Net hosted WebAPI services that must use an old library which depends heavily on HttpContext.Current. I am having trouble ensuring that context is preserved in all the methods that participate in an async call. I have tried several variations with await/Task.Wait and TaskScheduler.FromCurrentSynchronizationContext() on the below code.
[HttpGet]
public Task<IEnumerable<string>> ContinueWith()
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR"); //or another culture that is not the default on your machine
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
var output = new List<string> { TestOutput("Action start") };
var task = Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
return TestOutput("In Task");
}).ContinueWith(slowString =>
{
output.Add(slowString.Result);
output.Add(TestOutput("Action end"));
return output as IEnumerable<string>;
});
output.Add(TestOutput("Action Mid"));
return task;
}
private string TestOutput(string label)
{
var s = label + " ThreadID: " + Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture);
s += " " + Thread.CurrentThread.CurrentCulture.EnglishName;
s += HttpContext.Current == null ? " No Context" : " Has Context";
Debug.WriteLine(s);
return s;
}
我想能够确保的CurrentCulture是FR-FR,并且HttpContext.Current不是null在每个点处TestOutput被调用。我还没有成功地做到了,对于任何事情我都试过了在任务的号召。此外,在一些我的测试线程ID的亘古未变暗示我已经有效地清除了该方法的不同步。我怎样才能确保文化和HttpContext.Current是preserved在每次调用TestOutput,而code是自由地在不同的线程上运行?
I would like to be able to ensure that the CurrentCulture is fr-FR, and that HttpContext.Current is not null at each point where TestOutput is called. I have not succeeded in doing that for the "In Task" call with anything I have tried. Also in some of my test thread id never varies suggesting that I have effectively removed the asynchronicity of the method. How can I ensure that the culture and HttpContext.Current are preserved at each call to TestOutput, and that the code is free to run on different threads?
捕获HttpContext.Current在一个封闭,然后简单地重新设置它不会为我工作,我需要支持中等信任它调用的时候会抛出一个安全异常的HttpContext.Current的制定者。
Capturing HttpContext.Current in a closure and then simply setting it again will not work for me as I need to support Medium Trust which will throw a security exception when calling the HttpContext.Current setter.
上下文是preserved只要你计谋
任务。
Context is preserved whenever you await
tasks.
你看到的是,有没有上下文的线程池的任务( Task.Run
, TaskFactory.StartNew
,或者在这方面的BackgroundWorker
或发
或 Delegate.BeginInvoke
)。这是正常的和预期的。
What you're seeing is that there's no context for thread pool tasks (Task.Run
, TaskFactory.StartNew
, or for that matter BackgroundWorker
or Thread
or Delegate.BeginInvoke
). This is normal and expected.
所以,不使用线程池的任务。你比如code,似乎想要做并行处理,具有多线程的的HttpContext
,这根本是不可能的。
So, don't use a thread pool task. Your example code seems to want to do parallel processing with multiple threads having the HttpContext
, which simply isn't possible.
您可以执行并行异步
方法,如果你想要的,但是这需要你的 Thread.sleep代码
其实是可以一个异步
方法,而不是基于CPU的方法:
You can do concurrent async
methods if you want, but this requires that your Thread.Sleep
can actually be an async
method instead of a CPU-based method:
[HttpGet]
public async Task<IEnumerable<string>> Test()
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
var output = new List<string> { TestOutput("Action start") };
var task = SlowStringAsync();
output.Add(TestOutput("Action Mid"));
output.Add(await task);
output.Add(TestOutput("Action end"));
return output;
}
public async Task<string> SlowStringAsync()
{
await Task.Delay(1000);
return TestOutput("In Task");
}
如果你的老图书馆是在你的控制,你不能让它异步
,那么你就必须同步调用它。这是可以接受调用从异步
方法的同步方法在这样的情况:
If your old library is out of your control and you can't make it async
, then you'll have to call it synchronously. It's acceptable to call a synchronous method from an async
method in situations like this:
[HttpGet]
public async Task<IEnumerable<string>> Test()
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
var output = new List<string> { TestOutput("Action start") };
output.Add(TestOutput("Action Mid"));
Thread.Sleep(1000);
output.Add(TestOutput("Not Really In Task"));
output.Add(TestOutput("Action end"));
return output;
}