簡體   English   中英

當計時器從C#控制台應用程序中的其他類停止時如何返回main

[英]How to return to main when timer stopped from other class in c# console application

我有一個帶計時器的班級,如下所示

public class helper
{
    Timer timer = new Timer();
    private int counter = 0;
    private int returnCode = 0;


    public int Process()
    {
        SetTimer();
        Console.WriteLine("The application started ");
        return counter;

    }

    public void SetTimer()
    {
        int optionalWay = 0;
        // Create a timer with a two second interval.
        timer = new System.Timers.Timer(2000);
        // Hook up the Elapsed event for the timer. 
        timer.Elapsed += (sender, e) => OnTimedEvent(sender, e, optionalWay);         

        timer.AutoReset = true;
        timer.Enabled = true;

    }

    private void OnTimedEvent(Object source, ElapsedEventArgs e, int optionalWay)
    {
        counter++;
        Console.WriteLine("Timer is ticking");

        if (counter == 10)
        {
            timer.Stop();
            timer.Dispose();
            returnCode = returnCode + 1;
        }
    }       
}

我下面有這樣的主要功能

public static void Main()
{
    helper helper = new helper();
    int code = helper.Process();
    Console.WriteLine("Main " + code.ToString());
    Console.ReadLine();
}

我想做的是在計時器停止時而不是在此之前返回main

,我的計時器類運行正常,主要如下所示

所以main應該等到定時器的結果為1,然后結束進程

該代碼可以正常工作。 helper.Process()函數內部沒有任何東西可以等待或阻止執行,因此該函數會在執行OnTimedEvent之前立即返回到main函數。

解決方法可以通過在helper類中實現一個事件並在計時器完成其工作之后引發該事件來完成。 並且main可以收聽該事件並采取相應的行動。

public class helper
{
    Timer timer = new Timer();
    private int counter = 0;
    private int returnCode = 0;

    public event EventHandler<int> Done;
    ...

    private void OnTimedEvent(Object source, ElapsedEventArgs e, int optionalWay)
    {
        counter++;
        Console.WriteLine("Timer is ticking");

        if (counter == 10)
        {
            timer.Stop();
            timer.Dispose();
            returnCode = returnCode + 1;

            if (Done != null)
            {
                Done.Invoke(this, returnCode);
            }
        }
    }
}

並在Program.cs

static void Main(string[] args)
{
    helper helper = new helper();
    helper.Done += helper_Done;
    helper.Process();
    Console.ReadLine();
}

static void helper_Done(object sender, int e)
{
    Console.WriteLine("Main " + e.ToString());
}

更新資料

Timer類使用ThreadPool中的新線程執行Elapsed事件處理程序。 因此,它無法返回運行在不同線程上的Main 簡而言之:使用計時器無法實現您想做的事情。

這是使用Thread.Sleep()另一種解決方案,它將滿足您的要求,但是請記住, 不建議使用Thread.Sleep()這樣的解決方案。

public class helper
{
    private int counter = 0;
    private int returnCode = 0;

    public int Process()
    {
        Console.WriteLine("The application started ");
        StartTimer(2000);
        return returnCode;
    }

    private void StartTimer(int ms)
    {
        while (counter++ < 10)
        {
            System.Threading.Thread.Sleep(ms);
            Console.WriteLine("Timer is ticking");
        }
        returnCode = returnCode + 1;
    }
}

class Program
{
    static void Main(string[] args)
    {
        helper helper = new helper();
        int code = helper.Process();
        Console.WriteLine("Main " + code.ToString());
        Console.ReadLine();
    }
}

再次,這是使用一個很好的做法Thread.Sleep為延遲執行和Thread.Sleep是不准確的比較Timer.Elapsed 嘗試更改應用程序的設計,並使用事件回調函數

更改helper類的Process函數以接受回調:

public void Process(Action<int> callBack)
{
    SetTimer();
    Console.WriteLine("The application started ");
    if (timer != null)
        timer.Disposed += (o, e) => callBack(counter);
}

更改main函數以發送回調:

static void Main(string[] args)
{
    Console.WriteLine("Hello World!");

    helper helper = new helper();
    helper.Process(c => Console.WriteLine("Main " + c.ToString()));            
    Console.ReadLine();
}

我有兩個選擇,其中一個也是最丑的,就是循環直到計時器停止,基本上是這樣:

public class helper
{
    Timer timer = new Timer();
    private int counter = 0;
    private int returnCode = 0;
    private bool timerWorking = false;

    public int Process()
    {
        SetTimer();
        Console.WriteLine("The application started ");
        while(timerWorking){}
        return counter;
    }

    public void SetTimer()
    {
        // All the staff you already have
        timerWorking = true;
    }

    private void OnTimedEvent(Object source, ElapsedEventArgs e, int optionalWay)
    {
        counter++;
        Console.WriteLine("Timer is ticking");

        if (counter == 10)
        {
            //All the staff you already have
            timerWorking = false;
        }
    }
}

或者,更優雅的方式是,傳遞或注冊一個到達終點的回調:

public class helper
{
    Timer timer = new Timer();
    private int counter = 0;
    private int returnCode = 0;
    Action<int> _doAfterTimerEnds


    public void Process(Action<int> doAfterTimerEnds)
    {
        SetTimer();
        _doAfterTimerEnds = doAfterTimerEnds;
        Console.WriteLine("The application started ");
    }

    public void SetTimer()
    {
        int optionalWay = 0;
        // Create a timer with a two second interval.
        timer = new System.Timers.Timer(2000);
        // Hook up the Elapsed event for the timer. 
        timer.Elapsed += (sender, e) => OnTimedEvent(sender, e, optionalWay);         

        timer.AutoReset = true;
        timer.Enabled = true;
    }

    private void OnTimedEvent(Object source, ElapsedEventArgs e, int optionalWay)
    {
        counter++;
        Console.WriteLine("Timer is ticking");

        if (counter == 10)
        {
            timer.Stop();
            timer.Dispose();
            returnCode = returnCode + 1;
            _doAfterTimerEnds(returnCode)
        }
    }
}

public static void Main()
{
    var returnCode = 0;
    var helper = new helper();
    helper.Process(code => returnCode = code);

    while (returnCode != 1) {}

    Console.WriteLine("Main " + returnCode);
    Console.ReadLine();
}

更新 :我已經測試了最后一個版本,它正在按預期方式工作。

暫無
暫無

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

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