首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C# TaskCompletionSource不工作

C# TaskCompletionSource不工作
EN

Stack Overflow用户
提问于 2016-06-09 00:36:38
回答 2查看 1.1K关注 0票数 0

我有一个有趣的问题..我有一个工作的WCF服务的登录方法。

我创建了一个任务完成,并等待结果出现。

问题是,如果我调用两次login方法,第二次不会返回任何东西。我设置了断点,它进入已完成的事件,它调用了trysetresult,但没有返回任何内容。

以下是我的代码

代码语言:javascript
复制
    public Task<User> LoginByUserName(string userName, string password)
    {
        var tcs = new TaskCompletionSource<User>();

        if (!_registeredEventList.Contains ("LoginByUserNameCompleted")) {
            _registeredEventList.Add ("LoginByUserNameCompleted");


            userService.LoginByUserNameCompleted += (object sender, LoginByUserNameCompletedEventArgs args) => {
                if (args.Error != null)
                    tcs.TrySetException (args.Error);
                if (args.Result != null)
                    tcs.TrySetResult (args.Result);
                else
                    tcs.TrySetResult (null);

            };

        }

        userService.LoginByUserNameAsync (userName,password);
        return tcs.Task;
    }

我就是这样打电话的;

代码语言:javascript
复制
var loginResult= await Task.Run(()=>serviceHelper.LoginByUserName(userName,password));

例如,如果用户一次输入了错误的登录信息,在第二次尝试时,将不会返回任何信息。

PS:如果事件已被订阅,则_registeredEventList保持。如果是,那么它不会再次创建。当我删除那部分的时候,它就起作用了。

EN

回答 2

Stack Overflow用户

发布于 2016-06-09 04:26:11

正如Evk所评论的那样,问题在于您的代码有一个永远不会返回已完成任务的条件。具体地说,第一次调用此代码时,它将向_registeredEventList添加一个条目(该条目可能从未被删除过)。以后的所有调用都将返回一个永远不会完成的Task which is a major no-no in asynchronous programming

要解决此问题,我建议通过取消订阅作为回调的一部分来修改您的EAP包装器:

代码语言:javascript
复制
public static Task<User> LoginByUserNameTaskAsync(this UserService @this, string userName, string password)
{
  var tcs = new TaskCompletionSource<User>();
  LoginByUserNameCompletedDelegate callback = null;
  callback = (object sender, LoginByUserNameCompletedEventArgs args) =>
  {
    @this.LoginByUserNameCompleted -= callback;
    if (args.Error != null)
      tcs.TrySetException(args.Error);
    else
      tcs.TrySetResult(args.Result);
  };
  @this.LoginByUserNameCompleted += callback;

  @this.LoginByUserNameAsync(userName, password);
  return tcs.Task;
}

(我还将其作为扩展方法,并将其设置为follow the TAP naming parameters for TAP-over-EAP wrappers

票数 0
EN

Stack Overflow用户

发布于 2020-06-30 00:29:31

我刚刚解决了同样的问题。对我来说,它不是继承IDisposable并添加以下内容

代码语言:javascript
复制
public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed && disposing)
        {
            _channel?.Dispose();
            _connection?.Dispose();
        }

        this.disposed = true;
    }
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37708198

复制
相关文章

相似问题

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