【问题标题】:How to safely remove a delegate?如何安全地移除代表?
【发布时间】:2019-08-31 05:19:42
【问题描述】:

有人要求一个非常清晰的帖子。我正在尝试从我的主线程上的 Update 函数更新我的 UI。我试图通过使用委托来实现它,但它没有用。我的订阅者有时从辅助线程调用,有时从主线程调用,我该如何解决这个问题?我的更新功能中的内容会导致很多问题。

private void Update()
{
    if (update != null)
    {
        lock (update)
        {
            update.Invoke(oldState, state);
            update = null;
        }
    }
}

private void LoginSubscirber(AppState oldState, AppState state)
{
    lock (state)
    {
        if (oldState.loginState != state.loginState)
        {
            if (state.loginState == loginStateEnum.loadingLogin)
            {
                update = LoadingLoginCallback;
            }
            else if (state.loginState == loginStateEnum.successLogin)
            {
                update = LoginSuccescCallback;
            }
        }
    }
}

LoginSubscrirber(忽略我的拼写错误)有时用Task.Factory.StartNew() 调用

【问题讨论】:

标签: c# multithreading thread-safety task


【解决方案1】:

在对线程安全进行了更多搜索后,我最终使用了这种方法。我希望它在所有场景中都能正常工作:

ConcurrentQueue<MethodToExecute> threadSafeQueue = new ConcurrentQueue<MethodToExecute>();

    private void Update()
    {
        if (threadSafeQueue.Count > 0)
        {
            MethodToExecute changeUI;
            threadSafeQueue.TryDequeue(out changeUI);
            changeUI.action(changeUI.oldState, changeUI.state);
        }
    }

    private void Start()
    {
        StoreCreator.GetInstance.store.Subscribe += LoginSubscirber;
    }

    private void LoginSubscirber(AppState oldState, AppState state)
    {
        lock (state)
        {
            if (oldState.loginState != state.loginState)
            {
                if (state.loginState == loginStateEnum.loadingLogin)
                {
                    threadSafeQueue.Enqueue(new MethodToExecute(LoadingLoginCallback, oldState, state));
                }
                else if (state.loginState == loginStateEnum.successLogin)
                {
                    threadSafeQueue.Enqueue(new MethodToExecute(LoginSuccescCallback, oldState, state));
                }
                else if (state.loginState == loginStateEnum.failLogin)
                {
                    threadSafeQueue.Enqueue(new MethodToExecute(LoginFailCallback, oldState, state));
                }
                /*lock (oldState)
                {
                    this.oldState = oldState;
                    this.state = state;
                }*/
            }
        }
    }

【讨论】:

  • 如果您有任何建议,请帮助我
【解决方案2】:

你可以用这个:

var mDel = (RoutedEventHandler)delegate { clicked(a2, null); };

bxBox[z].Click += mDel ;

 ...

bxBox[z].Click -= mDel ;

【讨论】:

  • a2 和 bxBox 是什么意思?
  • int a2= 3; bxBox 是图片框。
  • 但这与我的情况有什么关系?我不明白。我怎样才能集成它?
  • 这并没有解决 OP 的问题,至少需要更多的上下文来理解这甚至与手头的问题有什么关系。
猜你喜欢
  • 2016-02-21
  • 2011-09-04
  • 2013-11-03
  • 2011-08-07
  • 2021-07-27
  • 1970-01-01
  • 1970-01-01
  • 2021-09-16
  • 2011-11-04
相关资源
最近更新 更多