繁体   English   中英

带线程C#窗口形式的计时器的想法

[英]Idea for Timer with thread C# Window Form

我的项目有一个MainForm,我显示F_Insert并为MainForm设置MdiParent

F_Insert f = new F_Insert();
f.MdiParent = this;  
f.Show();

在F_Insert中,我将带有CLick事件的按钮放在这样的位置

 private void btn_Add_Click(object sender, EventArgs e)
 {
       //Insert data to SQL
 }

此外,我想每5秒自动上传一次从F_Insert插入的数据

我使用System.Timer.Timer并将其设置为MainForm_Load中的Thread

Thread t1 = new Thread(new ThreadStart(Timerss)); //In MainFormLoad event
t1.Start(); 

public void Timerss()
    {
        System.Timers.Timer timer = new System.Timers.Timer(5000);
        timer.Elapsed += Timer_Insert_Tick;
        timer.AutoReset = true;
        timer.Start();
    }

private static void Timer_Insert_Tick(object sender, System.Timers.ElapsedEventArgs e)
    {
      //code auto upload data to server here
      //Data get from Sql Local to upload SQL in Server
    }

问题是它不能很好地工作。 我感觉当我插入数据形式F_Insert时,数据会受到MainForm加载中启动的Timerss线程的影响。

向您展示我的问题的简单方法是:当我将两个工作(插入并上传)分成两个不同的工作时,它工作正常,这意味着我插入了完整的数据,然后,我上传了数据,它将工作良好。 但是,当我同时插入数据和通过计时器自动上传数据时,我看到一些错误:连接SQL关闭或打开错误,没有数据从F_Insert获得,有时它获得了重复数据(旧数据)

请向我建议这个问题。 抱歉,但是我是新手。 谢谢 !!!

好吧,这取决于您尝试执行此代码的方式,但是我希望它可以为您提供一个起点。

首先让我们创建静态字段:

static volatile bool isDataChanged;

关键字volatile使此布尔型线程安全,这意味着当多线程环境中的任何线程访问此字段时,此字段始终保持最新(因此正确)的值。

我们需要此字段来保存bool值,该值稍后将用于检查数据是否被修改。

假设在click事件处理程序中修改了数据,则应将此标志设置为true:

 private void btn_Add_Click(object sender, EventArgs e)
 {
       // Data is modified in UI thread

       isDataChanged = true;
 }

然后,假设在Timer tick事件中,我们应该将最新数据上传到数据库(数据位于UI线程中,并且可能在两个tick事件之间的时间跨度中发生变化)。

首先,我们检查数据是否有任何更改,如果没有更改,我们只是退出该方法。 如果进行了更改,则需要将其上传到数据库,并且必须这样做,以便处理Timer线程中的数据可能与UI线程中的数据完全不同的事实。

让我们创建一个本地变量,该变量将保存从UI线程获取的正确数据,并使用this.Invoke()在UI线程上调用Func<object>委托。 委托附加的方法将从UI线程检索的正确数据的实例作为object 我们将其显式转换为数据的类型(通常是List<T>Dictionary<T1, T2>类的集合类型之一),然后使用此数据将其上传到数据库。

之后,由于数据库中的数据是正确的,因此将标志isDataChanged更改为false

private void Timer_Insert_Tick(object sender, System.Timers.ElapsedEventArgs e)
{
   if(!isDataChanged) return;

   // A very important line. It gets data from UI thread before uploading it
   // Change DataType with your data Type and dataToUpload with data instance

   DataType data = (DataType)this.Invoke(new Func<object>(() => dataToUpload));

   //use data to upload your data to server

   isDataChanged = false;
}

PS另外,最好将对我们Timer的引用放在外部作用域中(以便可以从表单内部的任何位置进行访问)

public partial class MyForm : Form
{
   ...
   System.Timers.Timer timer; 

   public void Timerss()
   {
      timer = new System.Timers.Timer(5000); 
   }

   ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM