0

我有一群“工人”,在某些时候需要来自我的 HTTP 服务器的唯一密钥才能继续执行。这些密钥有时会在工作人员需要它们之前到达,在这种情况下,我只想为工作人员提供密钥,以便它可以继续执行。但是,如果没有剩下的键,我希望任务中的代码执行停止,直到提供键。我还希望首先使用首先提供的密钥。

我试图实现一个单例,其中可以从 HTTP 服务器提供密钥并由工作人员从中检索,但现在执行似乎陷入僵局。

我的代码:

密钥处理程序.cs

public sealed class KeyHandler
{
    private static readonly KeyHandler instance = new KeyHandler();

    private static Dictionary<Website, Queue<string>> retrievedKeys = new Dictionary<Website, Queue<string>>();
    private static Dictionary<Website, Queue<TaskCompletionSource<string>>> waitingWorkers = new Dictionary<Website, Queue<TaskCompletionSource<string>>>();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static KeyHandler()
    {
    }

    private KeyHandler()
    {
        foreach (Website website in Enum.GetValues(typeof(Website)))
        {
            retrievedKeys.Add(website, new Queue<string>());
            waitingWorkers.Add(website, new Queue<TaskCompletionSource<string>>());
        }
    }

    public static KeyHandler Instance
    {
        get
        {
            return instance;
        }
    }

    public static void AddKey(Website website, string response)
    {
        if (waitingWorkers[website].Count > 0)
        {
            waitingWorkers[website].Dequeue().SetResult(response);
        }
        else
        {
            retrievedKeys[website].Enqueue(response);
        }
    }

    public static string RetrieveKey(Website website)
    {
        if (retrievedKeys[website].Count > 0)
        {
            return retrievedKeys[website].Dequeue();
        } 
        else
        {
            TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
            Task<string> t = tcs.Task;
            waitingWorkers[website].Enqueue(tcs);

            return t.Result;
        }
    }
}

工人.cs

    public async Task Run()
    {
        ...
        string key = KeyHandler.RetrieveKey(Website.MyWebsite);
        // do something with key here
        ...
    }

HTTPServer.cs

private void Process(HttpListenerContext context)
{
    ...
    KeyHandler.AddKey(Website.MyWebsite, key);
    ...
}
4

0 回答 0