How to serialize async/await?

后端 未结 4 2094
一向
一向 2020-12-29 12:26

Let\'s suppose I have this simple snippet:

async void button_Click(object sender, RoutedEventArgs e)
{
    await Task.Factory.StartNew(() =>
    {
                


        
4条回答
  •  感情败类
    2020-12-29 12:46

    I might be missing something, but I don't think SemaphoreSlim is needed for the OP's scenario. I'd do it the following way. Basically, the code just await the previous pending instance of the task before continuing (no exception handling for clarity):

    // the current pending task (initially a completed stub)
    Task _pendingTask = Task.FromResult(true);
    
    async void button_Click(object sender, RoutedEventArgs e)
    {
        var previousTask = _pendingTask;
    
        _pendingTask = Task.Run(async () =>
        {
            await previousTask;
    
            Console.WriteLine("start");
            Thread.Sleep(5000);
            Console.WriteLine("end");
        });
    
        // the following "await" is optional, 
        // you only need it if you have other things to do 
        // inside "button_Click" when "_pendingTask" is completed
        await _pendingTask;
    }
    

    [UPDATE] To address the comment, here's a thread-safe version, when button_Click can be called concurrently:

    Task _pendingTask = Task.FromResult(true);
    object _pendingTaskLock = new Object();
    
    async void button_Click(object sender, RoutedEventArgs e)
    {
        Task thisTask;
    
        lock (_pendingTaskLock)
        {
            var previousTask = _pendingTask;
    
            // note the "Task.Run" lambda doesn't stay in the lock
            thisTask = Task.Run(async () =>
            {
                await previousTask;
    
                Console.WriteLine("start");
                Thread.Sleep(5000);
                Console.WriteLine("end");
            });
    
            _pendingTask = thisTask;
        }
    
        await thisTask;
    }
    

提交回复
热议问题