Вызов асинхронного метода в службе WCF с одиночным InstanceContextMode - PullRequest
0 голосов
/ 21 декабря 2018

Я пытаюсь вызвать асинхронный метод в WCF, у которого есть один instanceContextMode.

Есть ли способ повторно использовать экземпляр службы, пока он ожидает асинхронный метод?Я использую способ Задачи для генерации асинхронных операций на моей ссылке на службу WCF.

Я создал проект тестирования, потому что у меня были некоторые проблемы с моим приложением.Мой TestService предоставляет 2 метода:

По некоторым другим причинам мой сервис долженбыть в Single instanceContextMode:

[ServiceContract]
public interface ITestService
{
    [OperationContract]
    string FastMethod(string name);

    [OperationContract]
    Task<string> LongMethodAsync(string name);
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class TestService : ITestService
{
    public TestService() { }

    public string FastMethod(string name)
    {
        Console.WriteLine($"{DateTime.Now.ToLongTimeString()} - FastMethod call - {name}");
        return $"FastMethod - {name}";
    }

    public async Task<string> LongMethodAsync(string name)
    {
        for (int i = 5; i > 0; i--)
        {
            await Task.Delay(1000);
            Console.WriteLine($"LongMethod pending {i}");
        }

        Console.WriteLine($"{DateTime.Now.ToLongTimeString()} - LongMethod call - {name}");
        return $"LongMethod - {name}";
    }
}

Мой хост - это простое консольное приложение, которое позволяет мне видеть вызовы WS через методы Console.WriteLine ():

class Program
{
    static void Main(string[] args)
    {
        using (ServiceHost hostTest = new ServiceHost(typeof(TestService)))
        {
            Console.WriteLine($"{DateTime.Now.ToLongTimeString()} - Service starting...");
            hostTest.Open();
            Console.WriteLine($"{DateTime.Now.ToLongTimeString()} - Service started");
            Console.ReadKey();
            hostTest.Close();
        }
    }
}

На моей стороне клиента,У меня есть только простая форма, которая показывает вызовы результата:

private async void button1_Click(object sender, EventArgs e)
{
    string result;
    result = srvClient.FastMethod("test1");
    resultTextBox.Text = $"{DateTime.Now.ToLongTimeString()} - {result}";

    Task<string> t1 = srvClient.LongMethodAsync("test2");

    result = srvClient.FastMethod("test3");
    resultTextBox.Text += $"\r\n{DateTime.Now.ToLongTimeString()} - {result}";

    System.Threading.Thread.Sleep(1000);
    result = srvClient.FastMethod("test4");
    resultTextBox.Text += $"\r\n{DateTime.Now.ToLongTimeString()} - {result}";

    result = await t1;
    resultTextBox.Text += $"\r\n{DateTime.Now.ToLongTimeString()} - {result}";
}

Когда я это делаю, я вижу в своей resultTestBox и в консоли хоста, что «test3» и «test4» вызываются только послеконец "test2".

Если я выполняю тот же тест локально (не через службу WCF), поведение будет таким, как ожидалось, "test3" и "test4" вызываются, пока "test2" ожидает.

1 Ответ

0 голосов
/ 21 декабря 2018

В соответствии с MSDN :

Если для значения InstanceContextMode задано значение Single, результат заключается в том, что ваша служба может обрабатывать только одно сообщение за один раз, если только вы не установили ConcurrencyModeзначение для ConcurrencyMode.

(похоже, они забыли сказать, что такое ConcurrencyMode)

Так что просто установите право ConcurrencyMode на вашем сервисе:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]

Убедитесь, что ваш код не имеет состояния и потокобезопасен.Эта комбинация очень подвержена ошибкам.

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