簡體   English   中英

c#異步調用方法

[英]c# asynchronously call method

這個類unit具有屬性bool status ,用於標記是否應在單元上調用方法, request 我有我的另一個類,在其中,有一個方法應該調用request 為了避免阻塞主線程,我想異步調用該方法。 問題是沒有狀態更改的事件,我不想讓我的異步調用做丑陋的事情,如:

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

要么

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

特別是當我不知道status變為true時間尺度時。

我該怎么做呢?

更新:我忘了提到我不能改變unit 對不起

您希望在屬性更改時調用函數(無論是否異步)。 你有兩個選擇:

  1. 附加到屬性更改時發出信號的偶數
  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");
    }
}

這輸出

Before
After
Manual blocking, or else app dies
Unit_OnChanged before
Unit_OnChanged after
Unit_OnChanged finished

這是典型的輪詢問題,在輪詢時確實沒有一個優雅的解決方案。 但是我們可以使用一些函數式編程來獲得一些不是噩夢的東西。

    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();

如果可能,請使用System.Threading.AutoResetEvent而不是bool

AutoResetEvent status = new AutoResetEvent();

在異步方法中,等待它:

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

然后,要在您的其他課程中發出信號,請致電Set

status.Set();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM