线程池中的计时器使用

时间:2011-03-04 16:17:51

标签: c# winforms multithreading timer threadpool

我正在为我的公司开发一个在服务器上运行的Windows应用程序。它是一个多线程应用程序,我正在使用线程池。

我的应用程序电子邮件模块包含3种主要方法。第一种方法从数据库获取新的广告系列,第二种方法决定通过电子邮件向谁发送广告系列,第三种方法发送广告系列。

当我启动应用程序时,第一种方法进入线程池,如果有新的广告系列,则使用广告系列信息调用第二种方法。但是当这些都发生时,如果有新的广告系列,第一种方法必须每三秒检查一次数据库。

我不确定是否必须使用System.Windows.Forms.Timer类或System.Threading.Timer ??

我不确定如何实施它?我是否会使用Invoke Function来调用主UI之外的线程?你能发一个示例代码并提出最佳实践吗? 非常感谢

这是我的代码:

private void btnStart_MouseClick(object sender, MouseEventArgs e)
    {
        smartThreadPool = new SmartThreadPool();
        workItemGroup = smartThreadPool.CreateWorkItemsGroup(1);
        workItemGroup.QueueWorkItem(CheckNewCampaigns);
        //smartThreadPool.QueueWorkItem(new WorkItemCallback(this.CheckNewCampaigns));            
    }

    private object CheckNewCampaigns(object state) // 1st method
    {
        StringBuilder builder = new StringBuilder();
        IEnumerable<Campaigns> CampaignsList = DatabaseManager.GetCampaignsList(DatabaseManager.GetNewCampaigns());

        foreach (Campaigns Campaign in CampaignsList)
        {
            builder.AppendFormat("New Campaign Arrived($) --> {0}\r\n", DateTime.Now.ToLongTimeString());
            builder.AppendFormat("CampaignID              --> {0}\r\n", Campaign.CampaignID);
            builder.AppendFormat("CustomerID              --> {0}\r\n", Campaign.CustomerID);
            builder.AppendFormat("ClientID                --> {0}\r\n", Campaign.ClientID);
            builder.AppendFormat("Title                   --> {0}\r\n", Campaign.Title);
            builder.AppendFormat("Subject                 --> {0}\r\n", Campaign.Subject);
            builder.AppendFormat("Status              --> {0}\r\n", Campaign.Status);
        }

        Console.WriteLine(builder.ToString());

        workItemGroup.QueueWorkItem(new WorkItemCallback(this.PrepareCampaignEmail), 2);
        return true;
    }

    private object PrepareCampaignEmail(object CampaignID)  // Second Method
    {
        int campaignID = (int)CampaignID;
        IEnumerable<Campaigns> CampaignDetailsList = DatabaseManager.GetCampaignsList(DatabaseManager.GetCampaignDetails(campaignID)); // bir tane campaign gelmekte
        IEnumerable<Subscribers> SubscribersList = DatabaseManager.GetCampaignSubscribersList(DatabaseManager.GetCampaignSubscribers(campaignID));
        ArrayList test = new ArrayList();

        DataTable dtCustomValuesForCampaign = DatabaseManager.GetCustomValuesForCampaign(campaignID);

        foreach (Subscribers subscriber in SubscribersList)
        {
            workItemGroup.QueueWorkItem(new WorkItemCallback(this.SendEmail), subscriber.Email);
        }

        return true;
    }

3 个答案:

答案 0 :(得分:1)

System.Thread.TimerWindows.Forms.Timer采取不同的行动。

System.Thread.Timer将在系统主题上运行。它有一个内部线程池,因此它不会在您明确创建的其中一个线程上运行。每个时间间隔,Timer池中的一个线程将运行您使用初始化对象的回调。

Windows.Forms.Timer会在当前主题上引发Tick事件,并且会在每个时间间隔内执行此操作,直到您将其禁用为止。

我无法告诉你哪种情况更适合你的情况;这取决于你是否想在UI线程上运行计时器,以及其他因素。

答案 1 :(得分:1)

在您的情况下,由于它是Windows窗体应用程序,并且您可能希望更新计时器事件处理程序中的UI,我建议使用Windows.Forms.Timer

使用Windows.Forms.Timer非常简单。在表单的设计视图中,从工具箱中选择Timer并将其放在表单上。然后,单击它以设置属性。您希望将Interval设置为3000(即3000毫秒),将Enabled设置为False

在Events选项卡上,双击Tick事件,IDE将为您创建一个处理程序。您希望事件处理程序看起来像这样:

private void timer1_Tick(object sender, EventArgs e)
{
    var stateObj = // create your state object here
    CheckNewCampaigns(stateObj);
}

您需要启动计时器(将Enabled设置为True)。您可以在Create事件处理程序中执行此操作,也可以在用户点击“开始”按钮时启用它。您也可以随时将Enabled设置为False来停止播放。

答案 2 :(得分:0)

试试这个:

public void EnableTimer()
        {
            if (this.InvokeRequired)
                this.Invoke(new Action(EnableTimer));
            else
                this.timer1.Enabled = true;
        }