Async WebApi Thread.CurrentCulture
Mam własny hostingOWIN hostowaneWeb API projekt zapewniający podstawowe metody REST.
Chcę mieć wielojęzyczne komunikaty o błędach, więc używamRatunek pliki iBaseController to ustawiaThread.CurrentCulture iThread.CurrentUICulture doAkceptuj-język nagłówek żądania.
public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
{
if (controllerContext.Request.Headers.AcceptLanguage != null &&
controllerContext.Request.Headers.AcceptLanguage.Count > 0)
{
string language = controllerContext.Request.Headers.AcceptLanguage.First().Value;
var culture = CultureInfo.CreateSpecificCulture(language);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
base.ExecuteAsync(controllerContext, cancellationToken);
}
To wszystko działa dobrze, ale problem pojawia się, gdy robię mójasynchroniczne metody kontrolera.
Kiedy używamoczekiwać w metodzie może być kontynuowany w innym wątku, a więc mójCurrentCulture iCurrentUICulture są zgubieni.
Oto mały przykład, którego użyłem do znalezienia tego problemu.
public async Task<HttpResponseMessage> PostData(MyData data)
{
Thread currentThread = Thread.CurrentThread;
await SomeThing();
if (Thread.CurrentThread.CurrentCulture != currentThread.CurrentCulture)
Debugger.Break();
}
Nie zawsze włamuję sięDebugger.Break line, ale większość czasu to robię.
Oto przykład, w którym faktycznie używam mojegoPlik zasobów.
public async Task<HttpResponseMessage> PostMyData(MyData data)
{
//Before this if I'm in the correct thread and have the correct cultures
if (await this._myDataValidator.Validate(data) == false)
//However, I might be in another thread here, so I have the wrong cultures
throw new InvalidMyDataException();
}
public class InvalidMyDataException : Exception
{
public InvalidMyDataException()
//Here I access my resource file and want to get the error message depending on the current culture, which might be wrong
: base(ExceptionMessages.InvalidMyData)
{
}
}
Kilka dodatkowych informacji: Mam całą masę wyjątków, takich jak ten, i wszystkie zostają wplątane w zwyczajExceptionFilterAttribute który następnie tworzy odpowiedź.
Dlatego byłoby dużo kodu, aby zawsze ustawiać kulturę tuż przed jej użyciem.