簡體   English   中英

使用Single InstanceContextMode在WCF服務上調用異步方法

[英]Call asynchronous method on a WCF service with Single InstanceContextMode

我試圖在具有單個instanceContextMode的WCF上異步調用一個方法。

有沒有辦法在等待異步方法時重用服務實例? 我使用Task方式在我的WCF服務引用上生成異步操作。

我做了一個測試項目,因為我的應用程序遇到了一些問題。 我的TestService公開了兩種方法:

    - 應該同步調用的快速方法
    - 一個應該異步調用的long方法

由於其他一些原因,我的服務應該在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}";
    }
}

我的主機是一個簡單的控制台應用程序,它允許我通過Console.WriteLine()方法查看WS調用:

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”等待時被調用。

根據MSDN

如果InstanceContextMode值設置為Single,則結果是您的服務一次只能處理一條消息,除非您還將ConcurrencyMode值設置為ConcurrencyMode。

(看起來他們忘了告訴ConcurrencyMode是什么)

所以只需在服務上設置正確的ConcurrencyMode

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

確保您的代碼是無狀態和線程安全的。 這種組合非常容易出錯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM