Silverlight:线程/延迟操作/异步调用/事件

时间:2009-02-26 13:38:09

标签: silverlight multithreading events asynchronous

我有以下情况:当用户将鼠标移出弹出窗口时,我想要动画发生,五秒钟之后,我想删除一个PopUp。

这是我期望执行此操作的代码:

private bool leftPopup = false;
public void AnimatePopupOut(object sender, MouseEventArgs e)
{
   myAnim.Begin();
   (new Thread(new ThreadStart(delayedRemovePopup))).Start();
}

private void delayedRemovePopup()
{
   leftPopup = true;
   Thread.Sleep(5000);
   PopUp.IsOpen = false;
}

第一行“leftPopup = true”没问题,但第三行“PopUp.IsOpen = false”给了我一个访问冲突异常,可能是因为这个对象属于GUI线程。有什么方法可以访问PopUp.IsOpen属性吗?如果没有,是否有其他方式可以在一段时间后调用事件来进行此操作?

干杯

的Nik

2 个答案:

答案 0 :(得分:3)

尝试使用PopUp.Dispatcher.Invoke()。这会将你的回调编组回UI线程。

答案 1 :(得分:1)

这是我在WPF中做的一个技巧。它被移植到Silverlight中使用并挂起Dispacher类。我不知道莫里斯的答案,因为我在SL5中没有看到“调用”方法。我确实看到了BeginInvoke,当谈到延迟行动时,这是无用的。

用法:您必须在代码文件中包含System.Windows命名空间,否则将不会显示此扩展方法。

// lets say you want to enable a control 1 second after a save event
// lets say you just want to prevent click happy users from going crazy
//   This code assumes you disabled the button on the click event
Button b = this.idButton1;
b.Dispatcher.DelayInvoke(TimeSpan.FromSeconds(1), () => { b.Enabled = true; });

就是这样。只需一行代码即可。下面是使上述代码成为可能的扩展类。

using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;

namespace System.Windows {

    public static class DispatcherExtensions {

        public static void DelayInvoke<TArg1, TArg2, TArg3>(this Dispatcher dispatcher, TimeSpan delay, Action<TArg1, TArg2, TArg3> action, TArg1 arg1, TArg2 arg2, TArg3 arg3) {
            dispatcher.DelayInvoke(delay, (Delegate)action, arg1, arg2, arg3);
        }

        public static void DelayInvoke<TArg1, TArg2>(this Dispatcher dispatcher, TimeSpan delay, Action<TArg1, TArg2> action, TArg1 arg1, TArg2 arg2) {
            dispatcher.DelayInvoke(delay, (Delegate)action, arg1, arg2);
        }

        public static void DelayInvoke<TArg1>(this Dispatcher dispatcher, TimeSpan delay, Action<TArg1> action, TArg1 arg1) {
            dispatcher.DelayInvoke(delay, (Delegate)action, arg1);
        }

        public static void DelayInvoke(this Dispatcher dispatcher, TimeSpan delay, Action action) {
            dispatcher.DelayInvoke(delay, (Delegate)action);
        }

        public static void DelayInvoke(this Dispatcher dispatcher, TimeSpan delay, Delegate del, params object[] args) {

            if (dispatcher == null)
                throw new NullReferenceException();
            if (delay < TimeSpan.Zero)
                throw new ArgumentOutOfRangeException("delay");
            if (del == null)
                throw new ArgumentNullException("del");

            var task = new Task(() => { Thread.Sleep(delay); });

            task.ContinueWith((t) => { dispatcher.BeginInvoke(del, args); });
            task.Start();
        }
    }
}