Руководство. Управление несколькими потоками в управляемом коде

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

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

Важно!

Следующие рекомендации используют интерфейсы API в Microsoft.VisualStudio.Threading пространстве имен, в частности JoinableTaskFactory класс. Интерфейсы API в этом пространстве имен являются новыми в Visual Studio 2013 . Экземпляр класса можно получить JoinableTaskFactory из ThreadHelper свойства ThreadHelper.JoinableTaskFactory .

Переключение из потока пользовательского интерфейса в фоновый поток

  1. Если вы работаете в потоке пользовательского интерфейса и хотите выполнять асинхронную работу в фоновом потоке, используйте Task.Run() :

    await Task.Run(async delegate{
        // Now you're on a separate thread.
    });
    // Now you're back on the UI thread.
    
    
  2. Если вы работаете в потоке пользовательского интерфейса и хотите синхронно блокироваться при выполнении работы в фоновом потоке, используйте TaskScheduler свойство TaskScheduler.Default внутри Run :

    // using Microsoft.VisualStudio.Threading;
    ThreadHelper.JoinableTaskFactory.Run(async delegate {
        await TaskScheduler.Default;
        // You're now on a separate thread.
        DoSomethingSynchronous();
        await OrSomethingAsynchronous();
    });
    

Переключение из фонового потока в поток пользовательского интерфейса

  1. Если вы находитесь в фоновом потоке и хотите сделать что-то в потоке пользовательского интерфейса, используйте SwitchToMainThreadAsync :

    // Switch to main thread
    await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
    

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

    Если фоновый метод потока не является асинхронным и его нельзя сделать асинхронным, вы по-прежнему можете использовать await синтаксис для переключения в поток пользовательского интерфейса путем создания оболочки работы с Run , как показано в следующем примере:

    ThreadHelper.JoinableTaskFactory.Run(async delegate {
        // Switch to main thread
        await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
        // Do your work on the main thread here.
    });