C # время компиляции, чтобы гарантировать, что методы вызываются только в потоке пользовательского интерфейса, а другие только в фоновом (не-пользовательском) потоке - PullRequest
5 голосов
/ 10 августа 2009

Прямо сейчас я делаю:

Util.AssertBackgroundThread ();

или

Util.AssertUIThread ();

в начале методов. Это не так уж плохо, но это проверка ошибок во время выполнения. Причина, по которой мы используем статические языки, такие как C #, заключается в том, чтобы перенести большую часть проверки ошибок на плечи компилятора.

Теперь я не думаю, что это обычно просто, но если я ограничусь только запуском потоков (или использую ThreadPool.QueueUserWorkItem) из своих собственных служебных методов, то мне кажется, что если я отмечу эти методы, Можно ли выполнить статический анализ, чтобы убедиться, что методы, предназначенные только для выполнения в потоке пользовательского интерфейса, действительно выполняются только в потоке пользовательского интерфейса?

Итак, два вопроса в одном здесь.

  1. Прав ли я, что это можно проверить во время компиляции?
  2. Есть ли практический способ сделать это в Visual Studio 2008 (с последним ReSharper установлен)

Ответы [ 2 ]

5 голосов
/ 10 августа 2009

Мне всегда нравился рисунок:

public void GuiMethod(object param)
{
   if(this.InvokeRequired)
   {
      this.Invoke(delgateToGuiMethod, params,...)
   }
   else
   {
      //perform gui thread method
   }
}

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

2 голосов
/ 10 августа 2009

Единственное, что я могу придумать, чтобы помочь вам, - это заставить ваши утверждения использовать #if DEBUG в своих телах, чтобы при выпуске методы были пустыми.

, например

public static void AssertUIThread()
{
#if DEBUG
   //the code goes here 
#endif
}

Таким образом, вы можете проверить во время разработки, правильно ли вы вызываете методы, и JIT полностью удалит вызов из вашего рабочего кода.

В данный момент я не вижу способа сделать это во время компиляции, но я предпочитаю этот вопрос в надежде, что на него будет дан ответ.

Edit:

Чем больше я думаю об этом, тем больше думаю, что вы сможете делать то, что хотите, используя пользовательское правило FxCop после компиляции. Дело в том, что ... я не знаю API самоанализа, который предоставляет FxCop, и он плохо документирован. Вернее, это совсем не задокументировано. Лучшее, что я могу для вас сделать, - предоставить учебник или два , который может вам помочь, а может и не помочь. Я в настоящее время в середине чтения их; если я найду что-нибудь интересное, выложу.

Редактировать 2:

Ахаха! Вы можете проанализировать вызывающего и вызываемого абонента метода . Используя указанное там руководство, создайте атрибут специально для методов, которые всегда должны вызываться из потока пользовательского интерфейса, а другой - для методов, которые должны вызываться только из отдельного потока. Ваше пользовательское правило проверяет один из этих атрибутов и запускается, только если метод имеет атрибут. Затем он анализирует вызывающие стороны этого метода (и их вызывающие и т. Д., Рекурсивно), пока не может определить, что вызывающая сторона находилась либо в потоке пользовательского интерфейса, либо в новом потоке.

Теперь мы подошли к сложной части. Я пока не смог разобраться с этой частью, и я оставляю вам возможность посмотреть, что вы можете придумать, так как уже поздно, и я не могу уделять много времени проблеме, но меня очень интересует решение. Проблема, с которой я продолжаю сталкиваться, заключается в том, что все потоки запускаются с использованием делегатов, и у меня возникает ощущение, что возникнут проблемы с дальнейшим продвижением по цепочке вызывающих абонентов, которой занимаются эти делегаты. Я не знаю, удастся ли получить от до делегата; если бы это было возможно, тип делегата можно было бы сравнить с известными делегатами потоков, чтобы определить, был ли выполнен вызов в новом потоке или нет.

Даже если это возможно, будет проблема прохождения от до делегата. Если вы не можете, вы можете быть уверены, до первого делегата, есть ли что-то в новом потоке.

Итак, проблемы для решения. Но, надеюсь, первый шаг для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...