Как я могу использовать поток, чтобы извлекать все новые уведомления в моей базе данных каждые x раз - PullRequest
0 голосов
/ 09 июня 2019

Я хочу получать список уведомлений каждые 15 секунд из моей базы данных, не делая мою программу очень медленной

Этот список уведомлений будет отображаться с помощью всплывающего уведомления

Проблема, с которой я сталкиваюсь, заключается в том, что при вызове метода для отображения всплывающих окон, если всплывающее окно отображается во вторичном потоке, а не в основном потоке

Я пробовал много способов, как использовать событие и вызывать событие всякий раз, когда прошло время, но просто вызывать обработчик события во вторичном потоке, единственное, чего я смог достичь, это использовать окно сообщения в тот же метод, что и у всплывающего уведомления, но выглядит он плохо и не поддается целям бэкэнда

  // This is the form that should show the notifications 
    private void Student_Details_Load(object sender, EventArgs e)
    {
        WinAPI.AnimateWindow(this.Handle, 200, WinAPI.BLEND);
        notifications.NewNotification += OnNewNotification;
        //This is a list of notifiactions        
        allNotifications = notifications.GetNotifications(StudentFound.Student.Person_ID);
        // calling the method to start the thread
         notifications.ShowNotifications();
        //This was an attempt to get it right
        //Thread notififcationThread = new Thread(new ThreadStart(() =>
        //{

        //    while (true)
        //    {
        //        AllNotifications = new 
         Notifications().GetNotifications(StudentFound.Student.Person_ID);

        //        //MethodInvoker invoker = new 
        MethodInvoker(showNotifications);
        //        //invoker.Invoke();
        //        //showNotifications();
        //        Thread.Sleep(5000);
        //    }
        //}));

        //notififcationThread.Start();

    }

    public void OnNewNotification(object sender,EventArgs e)
    {
        MessageBox.Show("You have notifications");
        PopupNotifier popup = new PopupNotifier();
        popup.Image = Properties.Resources.About_104px;
        popup.TitleText = "Smart Shool System";
        foreach (Notifications item in allNotifications)
        {
            popup.ContentText = item.Notification_Text;
            popup.Popup();
        }
    }

  // The method in the class that pulls the data
  public List<Notifications> GetNotifications(string userFound)
    {
        List<Notifications> allNotifications = new List<Notifications>();
        DataHandler dataHandler = new DataHandler();
        DataTable dataTable = new DataTable();

            dataTable = dataHandler.GetNotifications(userFound);
            foreach (DataRow rowItem in dataTable.Rows)
            {
                allNotifications.Add(new Notifications(int.Parse(rowItem["Notification_Id"].ToString()),
                    rowItem["Notification_text"].ToString(),
                    rowItem["Person_ID"].ToString(),
                    bool.Parse(rowItem["Notification_Status"].ToString())));
            }

        return allNotifications;

    }

  //EventHandler
    private void OnNewNotification()
    {
        if (NewNotification !=null)
        {
            NewNotification(this, EventArgs.Empty);
        }
    }
  //This is my current attempt this method is called in the frontend

    public void ShowNotifications()
    {
        //OnNewNotification();
        Thread notififcationThread = new Thread(new ThreadStart(() =>
        {

            while (true)
            {
                OnNewNotification();
                Thread.Sleep(5000);
            }
        }));
        notififcationThread.Start();

     }

Ответы [ 3 ]

0 голосов
/ 09 июня 2019

Вот как ты мог это сделать. Вы используете таймер WinForms, который вызывает событие каждые 15 секунд, вызывая ваш обработчик события. Ваш обработчик событий работает в потоке пользовательского интерфейса, и вы можете делать все, что захотите, для обновления пользовательского интерфейса. Вы можете извлечь данные в фоновом потоке и отобразить их с кодом в обработчике событий.

public partial class MyForm
{
    System.Windows.Forms.Timer _timer = new System.Windows.Forms.Timer();

    public MyForm()
    {
        InitializeComponent();
        // ...

        _timer.Interval = 15000; // Run Tick(s, e) event handler every 15 secs.
        _timer.Tick +=
            (s, e) =>
            {
                // Here you put whatever code you want to run at 15 secs
                // interval. Code is run on UI thread, so you can update
                // UI at will.
            }
    }
}
0 голосов
/ 11 июня 2019

Я изо всех сил пытаюсь понять поток, который вы хотите с вашим кодом, но вот способ, которым я буду заниматься любым обновлением пользовательского интерфейса, как это.

Вы должны использовать Microsoft Reactive Framework (иначе Rx) - NuGet System.Reactive.Windows.Forms и добавьте using System.Reactive.Linq; - тогда вы можете сделать это:

IDisposable subscription =
    Observable
        .Interval(TimeSpan.FromSeconds(5.0))
        .SelectMany(x => Observable.Start(() => GetTextData()))
        .ObserveOn(this)
        .Subscribe(x => control.Text = x);

Супер просто.

Вы можете позвонить subscription.Dispose(), чтобы остановить таймер.

0 голосов
/ 09 июня 2019

Вы можете сделать это в одном потоке с помощью async-await.

private CancellationTokenSource _displayNotification;
private Task _displayNotificationTask;

public StudentDetailsForm()
{
    _displayNotification = new CancellationTokenSource();
}

private void Student_Details_Load(object sender, EventArgs e)
{
    _displayNotificationTask = DisplayNotification(_displayNotification.Token);
}

private async void Student_Details_Closing(object sender, CancelEventArgs e)
{
    _displayNotification.Cancel();
    await _displayNotificationTask;
}

private async Task DisplayNotifications(CancellationToken cancellationToken)
{
    while (cancellationToken.IsCancellationRequested == false)
    {
        await LoadAndDisplayNotification();
        await Task.Delay(15000, cancellationToken);
    }
}

private async Task LoadAndDisplayNotification()
{
    // Load data and display it.
}

И вам нужно изменить код уведомления о загрузке, чтобы он был асинхронным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...