2015-01-10 6 views
3

Во время разработки приложения ASP.NET MVC я наткнулся на CultureAwaiter, экземпляр которого возвращается при вызове метода расширения WithCurrentCulture.ASP.NET Identity CultureAwaiter Code

Я относительно свежий для асинхронной модели Microsoft, поэтому я стараюсь понять интуицию за четырьмя строками в коде, который отмечен ниже. Обратите внимание, что я взял это из версии файла сборки «2.1.30612.0», используя ILSpy ... Я не думаю, что MS предоставила нам доступный источник.

В этих четырех строках, которые я предполагаю запускать синхронно в одном потоке, похоже, что переменная currentCulture установлена ​​на культуру текущего потока (пока это так хорошо). Две строки позже, однако, он просто берет эту переменную и устанавливает для нее текущую культуру потока (т. Е. Просто отменяет назначение). Какая польза от этого?

Культура UI, с другой стороны, имеет несколько иное поведение в этих четырех строках. Обратите внимание на случай «UI»/«Ui» в именах переменных. На второй из этих четырех строк переменная currentUICulture установлена ​​на пользовательский интерфейс текущего потока (предположительно, чтобы «запомнить» его для последующего использования). Две строки позже, культура пользовательского интерфейса текущего потока установлена ​​на другую переменную currentUiCulture (обратите внимание на другой случай) ..., определенный в начале метода.

В моем новичке понимание асинхронной модели в стороне, я бы по крайней мере ожидал, что и CurrentCulture, и CurrentUICulture имеют одинаковое поведение get/setting в этом методе. Я мог быть совершенно неправ, но мое чувство «кишки» говорит мне, что в этих четырех строках может быть неправильное назначение.

Может ли кто-нибудь пролить свет на это для моего понимания? Возможно, это связано с ILSpy?

// Microsoft.AspNet.Identity.TaskExtensions.CultureAwaiter<T> 
public void UnsafeOnCompleted(Action continuation) 
{ 
    CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture; 
    CultureInfo currentUiCulture = Thread.CurrentThread.CurrentUICulture; 
    this._task.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted(delegate 
    { 
     // WHAT'S GOING ON IN THE NEXT FOUR LINES? 
     CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture; 
     CultureInfo currentUICulture = Thread.CurrentThread.CurrentUICulture; 
     Thread.CurrentThread.CurrentCulture = currentCulture; 
     Thread.CurrentThread.CurrentUICulture = currentUiCulture; 
     try 
     { 
      continuation(); 
     } 
     finally 
     { 
      Thread.CurrentThread.CurrentCulture = currentCulture; 
      Thread.CurrentThread.CurrentUICulture = currentUICulture; 
     } 
    }); 
} 

ответ

3

Целью этого является выполнение продолжения с текущими настройками культуры, хотя оно может работать в другом потоке. Но мы не хотим постоянно изменять культуру этого потока, потому что у нас нет этого потока. Он поделился. Поэтому мы должны восстановить старые настройки перед выходом.

Возможно, декомпилятор просто показывает вводящие в заблуждение имена переменных. Отражатель делает это правильно:

public void UnsafeOnCompleted(Action continuation) 
{ 
    CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture; 
    CultureInfo currentUiCulture = Thread.CurrentThread.CurrentUICulture; 
    this._task.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted(delegate { 
     CultureInfo info1 = Thread.CurrentThread.CurrentCulture; 
     CultureInfo currentUICulture = Thread.CurrentThread.CurrentUICulture; 
     Thread.CurrentThread.CurrentCulture = currentCulture; 
     Thread.CurrentThread.CurrentUICulture = currentUiCulture; 
     try 
     { 
      continuation(); 
     } 
     finally 
     { 
      Thread.CurrentThread.CurrentCulture = info1; 
      Thread.CurrentThread.CurrentUICulture = currentUICulture; 
     } 
    }); 
} 
+0

Спасибо за отличный ответ. Похоже на причину оплаты Reflector :). – sammy34