7

私はWebサービスを使用しているので、セッションの長さを延長したり、再接続したり、大きなデータセットを取り戻したりする必要があります。これは時間がかかる場合があるため、UIを非同期に更新する別のスレッドで使用したかったのです。

同期コンテキストを使用してUIスレッドのメソッドを呼び出すことに頭を悩ませているようには見えません。UIThreadコンテキストをスレッドに渡したので、UIスレッドのラベルなどを更新したいと思います。私はたくさんの投稿を読んだことがありますが、いくつかのパラメーターをメソッドに戻す方法を説明しているものはないようです。

//メインUIスレッド

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

//別のスレッドで

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

sendOrPostCallBackを元のメソッドにリンクする方法を誰かが簡単に説明できれば、とてもありがたいです。

ありがとう

編集:

コードを実行してイベントを発生させようとすると、カスタム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 {};

//UIスレッドで今すぐ

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

2 に答える 2

19

SendOrPostCallbackタイプのデリゲートが必要です。これはかなり厄介ですが、オブジェクト型の引数を1つだけ取ります。これを簡単にするために、.NET4で利用可能なTask<>クラスを確認する必要があります。または、次のようにラムダを使用します。

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

{中括弧}の間のコードはUIスレッドで実行されます。

于 2012-08-19T18:47:29.387 に答える
7

通常、UIスレッドでタイプのインスタンス(ViewModelsなど)を作成しているため、SynchronizationContextまたはTaskScheduler(推奨されるIMHO)をプライベートフィールドに保存し、必要に応じて比較することができます...

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);
}
于 2013-09-23T17:50:54.260 に答える