private void RunAsync()
{
string param = "Hi";
Task.Run(() => MethodWithParameter(param));
}
private void MethodWithParameter(string param)
{
}
редактировать
По многочисленным просьбам я должен отметить, что Taskзапущенный будет работать параллельно с вызывающим потоком. Предполагая, что по умолчанию TaskSchedulerбудет использоваться .NET ThreadPool. В любом случае, это означает, что вам необходимо учитывать любой передаваемый параметр (ы) Taskкак потенциально доступный для нескольких потоков одновременно, делая их общим состоянием. Это включает доступ к ним в вызывающем потоке.
В моем приведенном выше коде этот случай совершенно спорный. Строки неизменны. Вот почему я использовал их в качестве примера. Но скажите, что вы не используете String...
Одно из решений - использовать asyncи await. Это, по умолчанию, захватывает SynchronizationContextвызывающий поток и создает продолжение для остальной части метода после вызова awaitи присоединяет его к созданному Task. Если этот метод выполняется в потоке графического интерфейса WinForms, он будет типа WindowsFormsSynchronizationContext.
Продолжение будет запущено после отправки обратно в захваченное SynchronizationContext- опять же только по умолчанию. Так что после awaitзвонка вы вернетесь к теме, с которой начали . Вы можете изменить это разными способами, в частности, используя ConfigureAwait. Короче говоря, остальная часть этого метода не будет продолжаться до тех пор , послеTask завершения другого потока. Но вызывающий поток будет продолжать работать параллельно, а не остальная часть метода.
Это ожидание завершения выполнения остальной части метода может быть или нежелательно. Если в дальнейшем ничто в этом методе не обращается к параметрам, переданным в, возможно, Taskвы вообще не захотите использовать await.
Или, может быть, вы используете эти параметры намного позже в методе. Нет причин awaitсразу же, так как вы можете спокойно продолжать работу. Помните, что вы можете сохранить Taskвозвращаемое значение в переменной, а awaitпозже - даже в том же методе. Например, когда вам нужно безопасно получить доступ к переданным параметрам после выполнения кучи другой работы. Опять же, вам не нужно делать awaitэто Taskсправа при запуске.
В любом случае, простой способ сделать это потокобезопасным по отношению к переданным параметрам Task.Run- это сделать следующее:
Вы должны сначала украсить RunAsyncс async:
private async void RunAsync()
Важная заметка
Желательно, чтобы отмеченный метод не возвращал void, как упоминается в связанной документации. Распространенным исключением из этого правила являются обработчики событий, такие как нажатие кнопки и т.п. Они должны вернуться в пустоту. В противном случае я всегда стараюсь вернуть или при использовании . Это хорошая практика по нескольким причинам.async TaskTask<TResult>async
Теперь вы можете awaitзапустить Taskкак показано ниже. Вы не можете использовать awaitбез него async.
await Task.Run(() => MethodWithParameter(param));
Итак, в целом, если вы awaitвыполняете задачу, вы можете избежать обработки переданных параметров как потенциально разделяемого ресурса со всеми подводными камнями изменения чего-либо сразу из нескольких потоков. Также остерегайтесь закрытия . Я не буду описывать их подробно, но связанная статья отлично справляется с этим.
Примечание
Немного не по теме, но будьте осторожны при использовании любого типа «блокировки» потока графического интерфейса WinForms из-за того, что он помечен значком [STAThread]. Использование awaitне будет блокировать вообще, но иногда я вижу, что оно используется в сочетании с какой-то блокировкой.
«Блокировать» заключено в кавычки, потому что вы технически не можете заблокировать поток графического интерфейса WinForms . Да, если вы используете lockпоток графического интерфейса WinForms, он все равно будет перекачивать сообщения, несмотря на то, что вы думаете, что он «заблокирован». Это не.
В очень редких случаях это может вызвать странные проблемы. Одна из причин, по которой вы никогда не захотите использовать lock, например, при рисовании. Но это крайний и сложный случай; однако я видел, как это вызывает сумасшедшие проблемы. Поэтому я отметил это для полноты картины.