3

ユニットでメソッド、、を呼び出す必要があるかどうかをマークunitするプロパティを持つこのクラスがあります。私には他のクラスがあり、その中に、を呼び出す必要のあるメソッドがあります。メインスレッドのブロックを回避するために、メソッドを非同期で呼び出したいと思います。問題は、ステータス変更のイベントがないことです。非同期呼び出しに次のような醜いことをさせたくありません。bool statusrequestrequest

while(!status){}unit.request(args);

また

while(!status){Thread.Sleep(100)}unit.request(args);

status特に、ターンのタイムスケールがわからない場合true

どうすればよいですか?

更新:変更できないことを忘れましたunit。そのために残念。

4

4 に答える 4

2

プロパティが変更されたときに(非同期であるかどうかにかかわらず)関数を呼び出したいとします。2つの選択肢があります。

  1. プロパティが変更されたときに通知される偶数にアタッチします
  2. プロパティの値を定期的に確認してください

あなたは最初をすることができないので、あなたは2番目をしなければなりません。

于 2012-08-19T14:06:47.817 に答える
2

これは、イベントを使用してこれを管理する方法のサンプルです。

これがあなたのクラスだとしましょう

public class Unit
{
    private readonly object _syncRoot = new object();
    private bool _status;

    public event EventHandler OnChanged;    

    public bool Status
    {
        get
        {
            lock (_syncRoot)
            {
                return _status;    
            }
        }
        set
        {
            lock (_syncRoot)
            {
                _status = value;
                if (_status && OnChanged != null)
                {
                    OnChanged.Invoke(this, null);        
                }
            }
        }
    }

    public void Process()
    {
        Thread.Sleep(1000);
        Status = true;
    }
}

これがあなたがそれを使うことができる方法です

class Program
{
    static void Main(string[] args)
    {
        var unit = new Unit();
        unit.OnChanged += Unit_OnChanged;
        Console.WriteLine("Before");
        Task.Factory.StartNew(unit.Process);
        Console.WriteLine("After");

        Console.WriteLine("Manual blocking, or else app dies");
        Console.ReadLine();
    }

    static void Unit_OnChanged(object sender, EventArgs e)
    {
        //Do your processing here
        Console.WriteLine("Unit_OnChanged before");
        Task.Factory.StartNew(()=>
        {
            Thread.Sleep(1000);
            Console.WriteLine("Unit_OnChanged finished");
        });
        Console.WriteLine("Unit_OnChanged after");
    }
}

この出力

前
後
手動でブロックしないと、アプリが停止します
Unit_OnChanged前
Unit_OnChanged後
Unit_OnChangedが終了しました
于 2012-08-19T14:22:01.407 に答える
1

これは古典的なポーリングの問題であり、ポーリングに関する場合、実際には洗練された解決策はありません。しかし、関数型プログラミングを使って、悪夢ではないものを使用することはできます。

    public static CancellationTokenSource Poll(
        Func<bool> termination,
        Action<CancellationToken> onexit,
        int waitTime = 0,
        int pollInterval = 1000)
    {
        var cts = new CancellationTokenSource();
        var token = cts.Token;
        Action dispose = cts.Cancel;

        var timer = new Timer(_ =>
        {
            if (termination() || token.IsCancellationRequested)
            {
                onexit(token);
                dispose();
            }
        }, null, waitTime, pollInterval);

        dispose = timer.Dispose;
        return cts;
    }

例:

    var condition = false;

    Poll(() => condition == true, ct => Console.WriteLine("Done!"));

    Console.ReadLine();

    condition = true;

    Console.ReadLine();
于 2012-08-19T14:29:27.350 に答える
0

可能であれば、のSystem.Threading.AutoResetEvent代わりに使用してください。bool

AutoResetEvent status = new AutoResetEvent();

非同期メソッドで、それを待ちます。

status.WaitOne();
unit.request(args);

次に、他のクラスでそれを通知するには、次のように呼び出しますSet

status.Set();
于 2012-08-19T14:22:47.517 に答える