Async/await в C#: подводные камни
Если не нужен вызов внутри потока UI предпочтительнее использовать
.ConfigureAwait(false);
return await Folder.CreateFileAsync(path, CreationCollisionOption.OpenIfExists).ConfigureAwait(false);
В статье как раз описан твой случай.
Ну и конечно лучше использовать await вместо Result
Если вы разрабатываете стороннюю библиотеку, очень важно всегда
настраивать await таким образом, чтобы остальная часть метода была
выполнена произвольным потоком из пула. Другими словами, в коде
сторонних библиотек всегда необходимо добавлять ConfigureAwait(false).
В первую очередь, сторонние библиотеки обычно не работают с UI
контролами (если конечно это не UI библиотека), поэтому нет никакой
необходимости связывать UI поток. Вы можете немного увеличить
производительность если позволите CLR выполнять ваш код любым потоком
из пула. Во-вторых, используя дефолтную имплементацию (или явно
проставляя ConfigureAwait(true)), вы оставляете потенциальную дыру для
дедлоков. Рассмотрим следующий пример:
private async void button1_Click(object sender, EventArgs e)
{
int result = DoSomeWorkAsync().Result; // 1
}
private async Task<int> DoSomeWorkAsync()
{
await Task.Delay(100).ConfigureAwait(true); //2
return 1;
}
Клик по кнопке здесь приводит к дедлоку. UI поток стартует новый I/O
поток на строке «2» и уходит в спящий режим на строке «1», ожидая
завершения работы. После того как I/O поток заканчивает выполнение,
оставшаяся часть метода DoSomeWorkAsync передается на выполнение
вызывающему (UI) потоку. Но тот в это время находится в спящем режиме,
ожидая завершения метода. Дедлок.
GetFile. – andreycha Apr 14 '16 at 14:16