简体   繁体   English

SynchronizationContext.Post到UI方法

[英]SynchronizationContext.Post to UI Method

I'm working with web services so its necessary for me to extend session length/reconnect and get large datasets back etc. Sometimes this can be lengthy so I wanted it in an separate thread that updates the UI asynchronously. 我正在使用Web服务,因此我需要扩展会话长度/重新连接并获取大型数据集等。有时这可能很长,所以我想在一个单独的线程中异步更新UI。

I can't seem to get my head around using the synchronizationContext to invoke a method on my UI thread. 我似乎无法理解使用synchronizationContext在我的UI线程上调用方法。 I have it whereby I have passed my UIThread context to my thread and now I want to update some labels etc on UI Thread. 我有它,我已经将我的UIThread上下文传递给我的线程,现在我想更新UI线程上的一些标签等。 I've read tons of posts but none seem to explain how to simply pass some parameters back to a method, or maybe they do but i'm too tired/stupid to have seen it. 我已经阅读了很多帖子,但似乎没有解释如何简单地将一些参数传递回方法,或者他们可能会这样做,但我太累了/傻到看不到它。

//On main UI Thread //在主UI线程上

public void updateConnStatus(string conn_name, bool connected)
{
        switch (conn_name)
        {
            case "Conn" : if (connected == true){ //do something} break;

//on separate Thread //在单独的线程上

uiContext.Post( //something to do with delegates in here that eludes me );

if someone could simply explain how I link the sendOrPostCallBack to the original method I would be very grateful. 如果有人可以简单地解释我如何将sendOrPostCallBack链接到原始方法,我将非常感激。

Thanks 谢谢

Edit: 编辑:

I managed to get the code to run and try to fire the event, it populates my custom eventArgs okay but either its saying that updateUIConnStatus has not been instantiated, needs more investigation :o 我设法让代码运行并尝试触发事件,它填充我的自定义eventArgs好,但要么说它没有实例化updateUIConnStatus,需要更多的调查:o

public void updateUIThread(string conn, bool connected)
    {
       uiContext.Post(new SendOrPostCallback((o) => { updateConnStatus(this, new MyEventArgs<String, Boolean>(conn, connected)); }), null);
    }

public class MyEventArgs<T, U> : EventArgs
    {
        private T _val1; private U _val2;
        public  MyEventArgs(T value1, U value2) { _val1 = value1; _val2 = value2; }
        public T val1 { get { return _val1;} }
        public U val2 { get {return _val2;} }
    }

public event EventHandler<MyEventArgs<String, Boolean>> updateConnStatus = Delegate {};

//on UI Thread Now //在UI Thread Now上

 public void updateConnStatus(object sender, MyEventArgs<String,Boolean> e)
    {
        switch (e.val1)
        {
            case "Conn1" :
                if (e.val2 == true)
                {

You need a delegate of type SendOrPostCallback. 您需要SendOrPostCallback类型的委托。 Which is pretty awkward, it only takes a single argument of type object . 这很尴尬,它只需要一个类型为object的参数。 You definitely ought to look at the Task<> class available in .NET 4 to make this easier. 你肯定应该看看.NET 4中提供的Task <>类来使这更容易。 Or use a lambda, like this: 或者使用lambda,如下所示:

        string conn_name = "foo";
        uiContext.Post(new SendOrPostCallback((o) => {
            updateConnStatus(conn_name, true);
        }), null);

The code between the { braces } executes on the UI thread. {braces}之间的代码在UI线程上执行。

Typically you are creating instances of your types (eg ViewModels) on the UI thread, so you can just save the SynchronizationContext or the TaskScheduler (preferable IMHO) to a private field and then compare it when needed... 通常,您在UI线程上创建类型的实例(例如ViewModels),因此您只需将SynchronizationContext或TaskScheduler(优选的恕我直言)保存到私有字段,然后在需要时进行比较...

private readonly SynchronizationContext _syncContext = SynchronizationContext.Current;
private readonly TaskScheduler _scheduler = TaskScheduler.Current;

void OnSomeEvent(object sender, EventArgs e)
{
    if (_syncContext != SynchronizationContext.Current)
    {
        // Use Send if you need to get something done as soon as possible.
        // We'll be polite by using Post to wait our turn in the queue.
        _syncContext.Post(o => DoSomething(), null);
        return;
    }
    // Call directly if we are already on the UI thread
    DoSomething();
}

void OnSomeOtherEvent(object sender, MyEventArgs e)
{
    var arg1 = e.Arg1; // "Hello "
    var arg2 = e.Arg2; // {"World", "!"};

    // Process args in the background, and then show the result to the user...
    // NOTE: We don't even need to check the context because we are passing
    // the appropriate scheduler to the continuation that shows a MessageBox.

    Task<string>.Factory.StartNew(() => ReturnSomething(arg1, arg2))
        .ContinueWith(t => MessageBox.Show(t.Result), _scheduler);
}

void DoSomething() { MessageBox.Show("Hello World!"); }

string ReturnSomething(string s, IEnumerable<string> list)
{
    return s + list.Aggregate((c, n) => c + n);
}

暂无
暂无

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

相关问题 SynchronizationContext.Post 到 UI 方法 - 更新多个标签 - SynchronizationContext.Post to UI Method - update multiple labels 传输事件处理程序中的SynchronizationContext.Post(…) - SynchronizationContext.Post(…) in transport event handler SynchronizationContext.Send和SynchronizationContext.Post有什么区别? - What is the difference between SynchronizationContext.Send and SynchronizationContext.Post? use invoke和synchronizationcontext.Post对象有什么区别? - What are difference between use invoke and synchronizationcontext.Post object? 为什么在使用多个等待时 SynchronizationContext.Post() 只被调用一次? - Why does SynchronizationContext.Post() get called only once when using multiple awaits? WindowsService的OnStart方法中SynchronizationContext为null - SynchronizationContext is null in OnStart method of WindowsService 在异步方法中更改SynchronizationContext - Changing SynchronizationContext Within Async Method 如何附加非UI线程的SynchronizationContext - How to attach SynchronizationContext of Non-UI thread 何时在UI应用程序中调用SynchronizationContext.SetSynchronizationContext()? - When to call SynchronizationContext.SetSynchronizationContext() in a UI application? 从另一个线程调用方法而不会阻塞该线程(或为非UI线程编写自定义SynchronizationContext)C# - call method from another thread without blocking the thread (or write custom SynchronizationContext for non-UI thread) C#
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM