하나의 List 데이터에 포함된 여러 주기만큼 반복되도록하는 코드

Infos에는 구간 데이터, ID가 포함
intervalDatas에는 구간별 데이터, ID, 데이터 갯수가 표함
30초 단위의 0, 1, 2, 3 ID구간이 반복되어
60초 단위에 4(0, 1 두번 사이클 포함), 5(2, 3 두번 사이클 포함)되어
각각 주기마다에 실행되는 코드

[Infos 데이터]
dataInfos

[원하는 결과 데이터]
result

void OnIntervalData()
{
uint checkTime = (uint)DateTime.Now.TimeOfDay.TotalSeconds;

 while(intervalThread != null)
 {
     DataInfo[] dataInfos = MainDataContext.DataInfoCollection.ToArray();
     try
     {
         if (dataInfo.IntervalData > 0)
         {
             IInfo[] Infos = dataInfo.LocationInfoCollection.ToArray();

             // PeriodIndex(초 단위 데이터)가 몇인지 몇개가 될지는 모름.
             var groupedInfos = Infos.GroupBy(x => x.PeriodIndex);

             // PeriodIndex로 구분되어진 group만큼 ListData를 복제함.
             // 현재 ListData는 다른 Thread에서 1초마다 Merge되고있음.
             foreach (var group in groupedInfos)
             {
                 // 원본 ListData를 Distinct 작업을 수행
                 ListData.Distinct();

                 // ListData를 복제하여 새로운 리스트에 저장 (현재 애매한 부분...)
                 // group에 속한 데이터를 처리를 어떻게 해야할지...
                 List<IntervalData> intervalDatas = group.Select(x => x.GetStandardDeviation(ListDataCopy)).ToList();

                 // intervalDatas를 이용하여 나머지 작업 수행
                 foreach (IntervalData i in intervalDatas)
                 {
                     // 작업 수행 코드
                     if ((checkTime % i.PeriodIndex) == 0)
                     {
                         #region 데이터처리
                         #endregion
                     }
                 }
                 // List Clear 시기는?
             }
         }
     }
     catch (Exception ex) { }

     #region TimeCheck
     checkTime++;
     double wait = (double)checkTime - DateTime.Now.TimeOfDay.TotalSeconds;
     if (wait > 0) Thread.Sleep((int)(wait * 1000.0));

     checkTime %= 86400;
     #endregion
 }

}

1 Like

질문에 나타난 식별자와 코드의 식별자가 거의 일치하지 않아 질문 자체를 이해하기 어렵군요.

꼭 필요한 정보는 소스 코드의 주석이 아니라, 질문의 문장 속에 넣어 보세요.
자신의 코드가 동작하지 않는다면, 차라리 적지 않는 게 좋습니다.

사용 중인 프레임워크, 닷넷 버전, 현재 상황, 필요한 결과로 요약해보세요.

2 Likes

보기 어려워 수정해서 달아놓습니다…

void OnIntervalData()
{
    uint checkTime = (uint)DateTime.Now.TimeOfDay.TotalSeconds;
    while (intervalThread != null)
    {
        DataInfo[] dataInfos = MainDataContext.DataInfoCollection.ToArray();
        try
        {
            if (dataInfo.IntervalData > 0)
            {
                IInfo[] Infos = dataInfo.LocationInfoCollection.ToArray();

                // PeriodIndex(초 단위 데이터)가 몇인지 몇개가 될지는 모름.
                var groupedInfos = Infos.GroupBy(x => x.PeriodIndex);

                // PeriodIndex로 구분되어진 group만큼 ListData를 복제함.
                // 현재 ListData는 다른 Thread에서 1초마다 Merge되고있음.
                foreach (var group in groupedInfos)
                {
                    // 원본 ListData를 Distinct 작업을 수행
                    ListData.Distinct();

                    // ListData를 복제하여 새로운 리스트에 저장 (현재 애매한 부분...)
                    // group에 속한 데이터를 처리를 어떻게 해야할지...
                    List<IntervalData> intervalDatas = group.Select(x => x.GetStandardDeviation(ListDataCopy)).ToList();

                    // intervalDatas를 이용하여 나머지 작업 수행
                    foreach (IntervalData i in intervalDatas)
                    {
                        // 작업 수행 코드
                        if ((checkTime % i.PeriodIndex) == 0)
                        {
                            #region 데이터처리
                            #endregion
                        }
                    }
                    // List Clear 시기는?
                }
            }
        }
        catch (Exception ex) { }

        #region TimeCheck
        checkTime++;
        double wait = (double)checkTime - DateTime.Now.TimeOfDay.TotalSeconds;
        if (wait > 0) Thread.Sleep((int)(wait * 1000.0));

        checkTime %= 86400;
        #endregion
    }
}
3 Likes

여기 계시는 분들이 친절하셔서 질문만 잘 올려주시면 답변 받으실 수 있으니 살펴보시고 보완해주세요^^

1 Like

원하시는 결과가 맞을 지 모르겠지만,

일정 주기 마다 이벤트를 발행하는 객체를 아래와 같이 정의할 수 있습니다.

public sealed class Ticker : IDisposable
{
    public Ticker(int intervalInSeconds) =>  _interval = intervalInSeconds;
    private CancellationTokenSource _cts = new();
    // bool : is the total tick count even?
    public event EventHandler<bool> Ticked = (s, e) => { };    
    public bool IsPausing => _skips;
    private bool _skips;    
    private bool _isBeating;
    private readonly int _interval;
    public void StartPause()
    {
        if(_isBeating is false) { Init(); _isBeating = true; return; }
        _skips = !_skips;
    } 

    private async void Init()
    {
        if(_isBeating) return;

        using var timer = new PeriodicTimer(TimeSpan.FromSeconds(_interval));
        
        bool isEven = false;     
        while (await timer.WaitForNextTickAsync(_cts.Token))
        {
            if(_skips) continue;
            if(_cts.IsCancellationRequested) break;
            Ticked.Invoke(null, isEven = !isEven);
        }     
    }

    public void Dispose() => _cts.Cancel();   
}

이 객체는 Ticked 이벤트를 발행할 때, 홀수 번 째 이벤트인지 짝수번째 이벤트인지를 알려 줍니다.

사용


internal class Program
{
    private static IEnumerable<int> Infos { get 
    {
        int infoId = 0;
        while(true) yield return infoId++;
    }}
    
    // 바인딩 소스
    private static readonly List<string> s_Results = [];

    private static void UpdateBindingSource(int count)
    {
        foreach (var id in Infos)
        {                            
            if(count-- <= 0 ) break;
            s_Results.Add($"id: {id}");
        }        
    }

    private static void TickedHandler(object? s, bool isEven) =>
        UpdateBindingSource( isEven ? 6 : 4);

    private static void Render()
    {
        if(s_Results.Count != 0) {
            System.Console.WriteLine(string.Join(" | ", s_Results));
            s_Results.Clear();
        }
    }

    static void Main(string[] args)
    {
        using var ticker = new Ticker(1);
        ticker.Ticked += TickedHandler;
        System.Console.WriteLine("Press s to toggle rendering or x to terminate");
                
        while(true)
        {
            Render();
            if (Console.KeyAvailable){
                var cki = Console.ReadKey(true);
                if (cki.Key == ConsoleKey.S) ticker.StartPause(); 
                else if(cki.Key == ConsoleKey.X)  break;     
            }             
        }
    }
}

UI 프레임워크를 사용 중일 것 같아 콘솔앱에 무한 루프를 넣었습니다.

결과

Press s to toggle rendering or x to terminate
(s 누름)
id: 0 | id: 1 | id: 2 | id: 3
id: 0 | id: 1 | id: 2 | id: 3 | id: 4 | id: 5
id: 0 | id: 1 | id: 2 | id: 3
id: 0 | id: 1 | id: 2 | id: 3 | id: 4 | id: 5

(s 누름) => 멈춤.
(s 누름) => 다시 시작.
(x 누름) => 종료.

1 Like