首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >windows phone 7中的锁异步方法

windows phone 7中的锁异步方法
EN

Stack Overflow用户
提问于 2014-01-28 18:25:42
回答 2查看 310关注 0票数 0

我正在使用自定义方法名称UploadDataToDropbboxAsync()将数据上传到按钮命令中的dropbox;我这样使用该方法。

代码语言:javascript
复制
 RelayCommand _navigateToDropBoxUploadCommand;
    public ICommand NavigateToDropBoxUploadCommand
    {
        get
        {
            return _navigateToDropBoxUploadCommand = _navigateToDropBoxUploadCommand ?? new RelayCommand(
                    async () =>
                    {
                        await UploadDataToDropbox("sandbox");
                    });
        }
    }

因此,当我在等待数据上传之前多次单击该按钮时,就会出现多个同时上传的情况。因此,我想对这个方法设置一个锁,以便在第一次上传完成之前不会再次调用它。任何帮助都是值得感激的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-28 18:38:03

我不会用锁定来解决这个问题。首先,您只处理一个线程-- UI线程(至少在锁定方面--因为您真正要求的是从运行此命令时锁定UI线程)。另外,它的重量比较重,做什么会是一个更好的方式来处理这件事。

我只需在异步之前禁用按钮,然后再重新启用它。例如:

代码语言:javascript
复制
return _navigateToDropBoxUploadCommand = _navigateToDropBoxUploadCommand ?? new RelayCommand(
    async () =>
    {
        myButton.IsEnabled = false;
        await UploadDataToDropbox("sandbox");
        myButton.IsEnabled = true;
    });

但是,禁用按钮可能最好在其他地方完成,这取决于您处理命令的方式等等.(例如,如果要对多个UI点击/单击事件重用此命令)。

票数 2
EN

Stack Overflow用户

发布于 2014-01-29 11:42:45

使用AsyncLock,可以创建一个上传队列,而不是同时上传:

代码语言:javascript
复制
private readonly AsyncLock _dropBoxUploadLock = new AsyncLock(); 

return _navigateToDropBoxUploadCommand = _navigateToDropBoxUploadCommand ?? new RelayCommand(
    async () =>
    {   
        var cachedStateFromUI = GetDataFromTheUI(...);
        using(var releaser = await _dropBoxUploadLock.LockAsync()) 
        {
            await UploadDataToDropbox(cachedStateFromUI);
        }
    });

使用的AsyncLock类来自Stephen http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266988.aspx的示例

代码语言:javascript
复制
  /*
   * private readonly AsyncLock m_lock = new AsyncLock(); 
   * … 
   * using(var releaser = await m_lock.LockAsync()) 
   * { 
   *     … // protected code here 
   * }
   */

  /// <summary>
  /// http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266988.aspx
  /// </summary>
  public class AsyncLock
  {
    private readonly AsyncSemaphore m_semaphore;
    private readonly Task<Releaser> m_releaser;

    public AsyncLock()
    {
      m_semaphore = new AsyncSemaphore(1);
      m_releaser = Task.FromResult(new Releaser(this));
    }

    public Task<Releaser> LockAsync()
    {
      var wait = m_semaphore.WaitAsync();
      return wait.IsCompleted ?
          m_releaser :
          wait.ContinueWith((_, state) => new Releaser((AsyncLock)state),
              this, CancellationToken.None,
              TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
    }

    public struct Releaser : IDisposable
    {
      private readonly AsyncLock m_toRelease;

      internal Releaser(AsyncLock toRelease) { m_toRelease = toRelease; }

      public void Dispose()
      {
        if (m_toRelease != null)
          m_toRelease.m_semaphore.Release();
      }
    } 
  }

AsyncLock依赖于AsyncSemaphore http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266983.aspx

代码语言:javascript
复制
  /*
   * private readonly AsyncSemaphore m_lock = new AsyncSemaphore(1); 
   * … 
   * await m_lock.WaitAsync(); 
   * try 
   * { 
   *     … // protected code here 
   * }  
   * finally { m_lock.Release(); }
   */

  /// <summary>
  /// http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266983.aspx
  /// </summary>
  public class AsyncSemaphore
  {
    private readonly static Task s_completed = Task.FromResult(true);
    private readonly Queue<TaskCompletionSource<bool>> m_waiters = new Queue<TaskCompletionSource<bool>>();
    private int m_currentCount;

    public AsyncSemaphore(int initialCount)
    {
      if (initialCount < 0) throw new ArgumentOutOfRangeException("initialCount");
      m_currentCount = initialCount;
    }

    public Task WaitAsync()
    {
      lock (m_waiters)
      {
        if (m_currentCount > 0)
        {
          --m_currentCount;
          return s_completed;
        }
        else
        {
          var waiter = new TaskCompletionSource<bool>();
          m_waiters.Enqueue(waiter);
          return waiter.Task;
        }
      }
    }

    public void Release()
    {
      TaskCompletionSource<bool> toRelease = null;
      lock (m_waiters)
      {
        if (m_waiters.Count > 0)
          toRelease = m_waiters.Dequeue();
        else
          ++m_currentCount;
      }
      if (toRelease != null)
        toRelease.SetResult(true);
    }
  }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21413777

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档