2014-08-29 2 views
10

В нашем приложении много вызовов Task.Factory.StartNew (Действие). К сожалению, при этом культура не установлена, и, кроме того, нет обработки ошибок. Я начал со стартовым классом, который будет делать так:Могу ли я перехватить Task.Factory.StartNew?

public static class TaskBuilder 
{ 
    private static Action<System.Exception> _exceptionCallback; 

    public static Task StartNew(Action action, CultureInfo cultureInfo, Action<System.Exception> exceptionCallback) 
    { 
     _exceptionCallback = exceptionCallback; 

     return Task.Factory.StartNew(() => 
     { 
      Thread.CurrentThread.CurrentUICulture = cultureInfo; 
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name); 

      action.Invoke(); 
     }).ContinueWith(t => ManageException(t.Exception), TaskContinuationOptions.OnlyOnFaulted); 
    } 

    private static void ManageException(System.Exception e) 
    { 
     if (_exceptionCallback != null) 
     { 
      _exceptionCallback(e); 
     } 
    } 
} 

Но потом я понял, что лучший подход был бы перехватчик. Я хотел бы перехватить вызов StartNew, чтобы новый поток содержал код обработки культуры и обработки ошибок. Моя попытка сделать это дает следующий код:

public class TaskInterceptionHandler : ICallHandler 
{ 
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) 
    { 
     Thread.CurrentThread.CurrentUICulture = // How do I get parent cultureInfo?; 
     Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name); 

     var methodReturn = getNext().Invoke(input, getNext); 

     if (methodReturn.Exception != null) 
     { 
      // How do I throw the exception to the calling thread here? 
     } 
     return methodReturn; 
    } 

    public int Order { get; set; } 
} 

Вот где я в тупик. Во-первых, как мне получить родительскую CultureInfo? Во-вторых Как вернуть исключение в вызывающий поток? и Как использовать этот класс в моих вызовах? То есть как заменить существующую Task.Factory.StartNew (..)

Я использую Unity, и здесь я незнакомая территория. Любая помощь или руководство будут оценены, или есть даже лучшее решение? Может, я начинаю с неправильной ноги?

Я использую .NET 4.5

Большая часть обратной связи я получаю ниже, кажется, чтобы избежать маршрут перехватчик. Можно ли предположить, что использование перехватчика - неправильный путь? Если кто-то может вести меня в этом направлении, это позволит мне сделать сравнение. Если ответ на вопрос «да», я хотел бы знать, как это сделать?

+0

Какая версия .NET вы используете? .NET 4.5 имеет свойство CultureInfo.DefaultThreadCurrentCulture (и его эквивалент UICulture), который позволяет устанавливать культуру для всех потоков в домене приложения. –

+0

Я использую .NET 4.5 – Ray

+1

Исключительный материал должен обрабатываться кодом, вызывающим «StartNew», проверяющим возвращенную «Задачу», а не передачей обратного вызова для выполнения, когда есть исключение. Вы обращаетесь к обработке ошибок TPL, которая является одной из наиболее полезных функций. – Servy

ответ

1

Вместо того, чтобы устанавливать культуру в каждой задаче, я предлагаю вам установить свойства CultureInfo.DefaultThreadCurrentCulture и CultureInfo.DefaultThreadCurrentUICulture, чтобы установить культуру в глобальном масштабе для всех будущих потоков.

Что касается обработки ошибок, это, вероятно, проще использовать await в Try/поймать блок, а не передавая делегат для обработки исключения:

try 
{ 
    // Task.Run is similar to Task.Factory.StartNew, but easier to use 
    await Task.Run(...); 
} 
catch(Exception ex) 
{ 
    // handle it... 
} 

BTW, текущий механизм обработки ошибок не будет работать, если у вас есть несколько задач одновременно, так как для всех задач есть только один _exceptionCallback ...

+0

Но где я могу поставить эту попытку поймать? – Ray

+0

@ Ray, поместите его в те места, где вы называете 'Task.Factory.StartNew' (и не забывайте' await') –