Client Пример кода:WCF клиент висит на любой операции после того, как ожидание асинхронной операции в консоли Application
var f = new DuplexChannelFactory<IService>(new Callback(), "NetTcpBinding_Name");
f.Credentials.ClientCertificate.Certificate = new X509Certificate2(certificateFile, "", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
f.Open();
IService s = f.CreateChannel();
Console.WriteLine("Lock status: " + s.IsUserLocked(id));
Task task = s.LockUserAsync(id);
Console.Write("Sent, awaiting ");
Console.WriteLine(task);
await task;
Console.WriteLine("Done");
Console.WriteLine("Lock status: " + s.IsUserLocked(id)); // never returns, timeout
После того, как ожидает от способа асинхронной LockUserAsync
любые способы синхронизации повесить навсегда. Отладчик показывает, что IsUserLocked
на самом деле называется во второй раз и достиг своего возвращения.
Это не влияет на других клиентов: они могут подключаться и повторять одно и то же с самого начала.
Поведение:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple)]
Контракт:
[ServiceContract(CallbackContract = typeof(IServiceCallback))]
public interface IService
{
[OperationContract]
Task LockUserAsync(int userId);
[OperationContract]
int IsUserLocked(int id);
}
public interface IServiceCallback
{
[OperationContract]
void TestCallback(); // not used
}
Оба метода просто заполнители:
public async Task LockUserAsync(int id)
{
return;
}
public int IsUserLocked(int id)
{
return 0;
}
Update: это консольное приложение, так что нет контекста синхронизации. Если я заменю await
с .Wait()
, он будет работать. ConfigureAwait(false)
ничего не меняет.
Я обнаружил, что продолжение так или иначе вызвано прямо из Task.SetResult
. Почему он не вызывается через ThreadPool
?
В приложении Console метод 'Main' не может быть' async', поэтому в конечном итоге вам придется вызывать '.GetAwaiter(). GetResult()' внутри этого 'Main' метода, чтобы ждать всех асинхронных методов завершить. Конечно, внутри этих методов async вы можете использовать ключевое слово 'await' при вызове webservices. –
@DarinDimitrov Да, я уже делаю так, иначе он не будет компилироваться. – Vlad