Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 跨线程同步异步任务_C#_Multithreading_Asynchronous - Fatal编程技术网

C# 跨线程同步异步任务

C# 跨线程同步异步任务,c#,multithreading,asynchronous,C#,Multithreading,Asynchronous,试图找出为这个问题设计解决方案的最佳方法 处理身份验证中间件时的HTTP请求管道。在JWTBeareOptions中运行OnTokenValidated与我的请求代码并行执行。我可以同步运行,但我不希望 我的一些请求需要此索赔,我如何才能确保此索赔已确定 我正在运行两个并行线程 一个异步函数依赖于另一个线程来设置变量 我创建了一个等待经理来完成我的任务 然而,等待管理器可能没有为任务设置键,因为我没有执行 我的代码: public class TaskManager : ITaskManager

试图找出为这个问题设计解决方案的最佳方法

处理身份验证中间件时的HTTP请求管道。在JWTBeareOptions中运行OnTokenValidated与我的请求代码并行执行。我可以同步运行,但我不希望

我的一些请求需要此索赔,我如何才能确保此索赔已确定

  • 我正在运行两个并行线程
  • 一个异步函数依赖于另一个线程来设置变量
  • 我创建了一个等待经理来完成我的任务
  • 然而,等待管理器可能没有为任务设置键,因为我没有执行 我的代码:

    public class TaskManager : ITaskManager
    {
    
        Dictionary<string, Task> _taskAwaiterMap = new Dictionary<string, Task>();
        public Task GetTaskForKey(string key)
        {
            this._taskAwaiterMap.TryGetValue(key, out var awaiter);
            return awaiter;
        }
    
        public void QueueTask(string key, Task task)
        {
            this._taskAwaiterMap[key] = task;
        }
    }
    
    公共类任务管理器:ITaskManager
    {
    Dictionary _taskAwaiterMap=新字典();
    公共任务GetTaskWorkey(字符串键)
    {
    此._taskAwaiterMap.TryGetValue(键,输出变量等待器);
    返回等待者;
    }
    公共无效队列任务(字符串键,任务任务)
    {
    此._taskAwaiterMap[key]=任务;
    }
    }
    
    编辑

    public async Task GetManditoryTaskForKey(string key, int timeout)
    {
        var cancellationTokenSource = new CancellationTokenSource(timeout);
        await GetManditoryResolverWaitTask(key, cancellationTokenSource.Token);
    }
    
    protected async Task<Task> GetManditoryResolverWaitTask(string key, CancellationToken cancellationToken)
    {
        while (false == this._taskAwaiterMap.TryGetValue(key, out var task))
        {
            if(cancellationToken.IsCancellationRequested)
            {
                return Task.FromCanceled(cancellationToken);
            }
            await Task.Yield();
        }
    
        return this.GetTaskForKey(key);
    }
    
    公共异步任务GetManditoryTaskWorkey(字符串键,int超时)
    {
    var cancellationTokenSource=新的cancellationTokenSource(超时);
    等待GetManditoryResolverWaitTask(key,cancellationTokenSource.Token);
    }
    受保护的异步任务GetManditoryResolverWaitTask(字符串键,CancellationToken CancellationToken)
    {
    while(false==this.\u taskAwaiterMap.TryGetValue(key,out var task))
    {
    if(cancellationToken.IsCancellationRequested)
    {
    返回任务.fromCancelled(cancellationToken);
    }
    等待任务;
    }
    返回此.gettaskWorkey(键);
    }
    
    我已经找到了一种等待设置密钥的方法,但这是同步异步任务的有效方法吗

    编辑

    在我的Http管道中,我会将任务排队,如下所示:

    OnTokenValidated = async tvc => { await AuthenticationRule.ValidateToken(tvc); }
    
    //... Source ValidateToken
    //Some Potentially long Task
    var awaitManager = serviceProvider.GetRequiredService<ITaskManager>();
    var userClaimsTask = SetUserClaims(claimsIdentity, context, userSubjectId);    
    awaitManager.QueueTask(USER_CLAIM_AWAITER_KEY, userClaimsTask);
    
    OnTokenValidated=async tvc=>{await AuthenticationRule.ValidateToken(tvc);}
    //... 源代码验证
    //一些潜在的长期任务
    var waitmanager=serviceProvider.GetRequiredService();
    var userClaimsTask=SetUserClaims(claimsIdentity、context、userSubjectId);
    waitmanager.QueueTask(用户\声明\等待者\密钥,userClaimsTask);
    

    如何有效地同步异步任务?

    我正试图回答您前面的问题。:)

    无论如何,我不确定这是否是解决您问题的最佳解决方案,因为我不熟悉异步HTTP管道。但以下是您正在采取的方法的解决方案:

    public class TaskManager : ITaskManager
    {
        private readonly ConcurrentDictionary<string, TaskCompletionSource<Task>> _taskAwaiterMap = new ConcurrentDictionary<string, TaskCompletionSource<Task>>();
    
        public async Task GetTaskForKey(string key)
        {
            await await this._taskAwaiterMap.GetOrAdd(key, _ => new TaskCompletionSource<Task>()).Task;
        }
    
        public void QueueTask(string key, Task task)
        {
            this._taskAwaiterMap.GetOrAdd(key, _ => new TaskCompletionSource<Task>()).SetResult(task);
        }
    }
    
    公共类任务管理器:ITaskManager
    {
    私有只读ConcurrentDictionary_taskAwaiterMap=new ConcurrentDictionary();
    公共异步任务GetTaskWorkey(字符串键)
    {
    等待此操作。_taskAwaiterMap.GetOrAdd(键,=>newtaskcompletionsource()).Task;
    }
    公共无效队列任务(字符串键,任务任务)
    {
    这是._taskwaitermap.GetOrAdd(键,=>newtaskcompletionsource()).SetResult(任务);
    }
    }
    

    我假设TaskManager将只在会话中运行。否则,您将不得不考虑如何清理
    \u taskAwaiterMap

    您可以使用
    TaskCompletionSource
    让一个执行流使用TPL唤醒另一个执行流。@MarcinJuraszek谢谢,你是否有我可以用来开始研究如何做的信息或资源?这个问题似乎与你没有实质性的不同。请找出你真正想要的答案,并删除另一个。但是,请注意,这两个方面仍然过于宽泛。您既没有简化场景,也没有创建一个完整的代码示例来说明简化的场景。就目前情况而言,有太多可能的答案,无法知道哪一个是你可以接受的。@PeterDuniho很抱歉,这个问题本来是要删除的。我只是使用部分文本作为参考。如果一个线程在另一个线程上等待,那么您真的需要两个线程吗?有没有其他方法可以解决这个问题,从而使两个线程之间没有任何依赖关系?查看实际问题的代码会很有帮助。@llianPinzon感谢您再次找到此线程,它看起来很完美,我需要测试它out@johnny5修复了
    gettaskworky
    中的一个错误。请注意这两个等待。@llianPinzon,我如何才能确保已为此设置了密钥?
    GettaskWorkey
    将为给定密钥创建一个未完成的TaskCompletionSource,即使尚未调用
    QueueTask
    。这就是
    GetOrAdd
    的目的。但是只有
    QueueTask
    可以完成TaskCompletionSource。@johnny5基本上,
    gettaskWorkey
    将创建键,如果它还不在那里。