【问题标题】:How to wait for all responses of WCF Method ?如何等待 WCF 方法的所有响应?
【发布时间】:2014-06-12 14:41:04
【问题描述】:

我有 WCF 方法,它获取所有玩家(客户)的分数并将它们添加到他们的列表中进行排序。

但不幸的是,当第一个分数发送到服务器时,该函数将其添加到列表中并将排序后的列表发送到客户端,不需要等待其他玩家的所有其他分数。 我尝试使用 async & await 来延迟该方法的继续大约 30 秒,如下所示:

 public  List<Player>  GetListOfWinners(int SentScore , string _SentPlayerID )
    {
        List<Player> PlayersList = new List<Player>();
        //Add to the List 
        PlayersList.Add(new Player { PlayerID = _SentPlayerID, Score = SentScore });

        DelayMethod();
        //Order It
        List<Player> SortedList = PlayersList.OrderByDescending(p => p.Score).ToList(); 
        // sent fULL SORTHEDlist to the Clients
        return SortedList;

    }

    private async void DelayMethod()
    {
        await Task.Delay(30000);
    }

但它不起作用,那我该怎么办?

【问题讨论】:

  • 这个方法会同时被每个玩家调用吗?我只看到一名球员得分被发送
  • 是的,一开始会为所有玩家发送数独游戏,在固定的时间后客户端为每个玩家计算分数并将其发送到服务器端为此方法(GetListOfWinners)
  • 有些东西我不明白。您为每个请求创建一个新列表,添加一个玩家,然后对列表进行排序?这没有任何意义。
  • 这对我来说也没有意义。请描述一下,这种方法到底应该做什么。其他玩家应该从哪里来?
  • @YuvalItzchakov .. 嗯,我刚刚意识到服务器会为每个不应该发生的请求创建一个新列表。

标签: c# multithreading wcf


【解决方案1】:

我创建了一个非常基本的服务作为示例,以展示您可以如何实现某些目标。提供它是为了向您介绍lockManualResetEvent 等结构。

在我的 ISudokuConcurrentService.cs 中:

namespace SudokuTest
{
    using System.Collections.Generic;
    using System.Runtime.Serialization;
    using System.ServiceModel;

    [ServiceContract]
    public interface ISudokuConcurrentService
    {
        [OperationContract]
        SudokuGame ClientConnect();

        [OperationContract]
        List<Player> GetListOfWinners(int SentScore, string _SentPlayerID);
    }

    [DataContract]
    public class SudokuGame
    {
        [DataMember]
        public string PlayerID { get; set; }
        [DataMember]
        public int TimeLimitInSeconds { get; set; }
    }

    [DataContract]
    public class Player
    {
        [DataMember]
        public string PlayerID { get; set; }
        [DataMember]
        public int Score { get; set; }
    }
}

在我的 SudokuConcurrentService.svc.cs 中:

namespace SudokuTest
{
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;

    public class SudokuConcurrentService : ISudokuConcurrentService
    {
        static int playerCount = 0;
        static List<Player> PlayersList = null;
        static object ListLock = new object();
        const int TimeLimit = 120;
        static ManualResetEvent AllPlayerResponseWait = new ManualResetEvent(false);

        public SudokuGame ClientConnect()
        {
            lock (ListLock)
            {
                if (PlayersList != null)
                {
                    // Already received a completed game response -- no new players.
                    return null;
                }
            }
            return new SudokuGame()
                {
                    PlayerID = "Player " + Interlocked.Increment(ref playerCount).ToString(),
                    TimeLimitInSeconds = TimeLimit
                };
        }

        public List<Player> GetListOfWinners(int SentScore, string _SentPlayerID)
        {
            lock (ListLock)
            {
                // Initialize the list.
                if (PlayersList == null) PlayersList = new List<Player>();

                //Add to the List 
                PlayersList.Add(new Player { PlayerID = _SentPlayerID, Score = SentScore });
            }

            // Now decrement through the list of players to await all responses.
            if (Interlocked.Decrement(ref playerCount) == 0)
            {
                // All responses received, unlock the wait.
                AllPlayerResponseWait.Set();
            }

            // Wait on all responses, as necessary, up to 150% the timeout (no new players allowed one responses received, 
            // so the 150% should allow time for the last player to receive game and send response, but if any players have 
            // disconnected, we don't want to wait indefinitely).
            AllPlayerResponseWait.WaitOne(TimeLimit * 1500);

            //Order It
            List<Player> SortedList = PlayersList.OrderByDescending(p => p.Score).ToList();
            // sent fULL SORTHEDlist to the Clients
            return SortedList;

        }
    }
}

请注意,此示例的主要限制是它只允许在服务的生命周期内玩单个游戏。我将把多场比赛作为练习留给你,但会指出你需要跟踪每场比赛现在所做的一切。您可能希望将列表和等待锁捆绑到对象中,然后您可以以某种方式存储另一个列表,例如MemoryCache

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-14
    • 2022-01-06
    相关资源
    最近更新 更多