繁体   English   中英

如何安全地移除委托?

[英]How to safely remove a delegate?

有人要求一个非常明确的帖子。 我正在尝试从我的主线程上的 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()调用

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

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;
                }*/
            }
        }
    }

你可以使用这个:

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

bxBox[z].Click += mDel ;

 ...

bxBox[z].Click -= mDel ;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM