如何在C#中排队用户工作项后执行线程池?

时间:2016-02-22 07:44:23

标签: c# multithreading

我是C#编程的新手,我有一个任务来完成从单线程到多线程的进程。我正在使用C#3.5版本并在代码中实现线程池。我搜索了关于线程池并进行了一些更改,但它无法正常工作。当我再次在互联网上搜索时,我认为我只编写了部分代码,只排队用户工作项,我不了解如何执行线程。

这里显示的是我编写的代码,如果代码错误,请随时纠正我,我对C#编码很新。

ThreadPool.SetMaxThreads(6, 6);

try
{
    // Assign the values to the report parameters
    for (int i = 0; i < aq.Count; i++)
    {
        object j = aq[i];
        ThreadPool.QueueUserWorkItem(new WaitCallback(process), j);
    }
}            
   private void process(object i)
    {

        List<Report> aq = new List<Report>();
        ReportEnv env = null;
        ParameterValue[] paramval;

        List<Report> list = new List<Report>();
        Report al = null;

        using (OleDbDataAdapter oleDA = new OleDbDataAdapter())
        using (DataTable dt = new DataTable())
        {
            oleDA.Fill(dt, i);

            foreach (DataRow _row in dt.Rows)
            {
                al = new Report();

                al.EmailAttachmentMsg = _row["AttachmentMsg"].ToString();
                al.reportName = _row["Repo"].ToString();
                al.AccountNumber = _row["Number"].ToString();
                al.AccountGroupCode = _row["GroupCode"].ToString();
                al.EmailTo = _row["To"].ToString().Split(';');
                al.ReportScheduleId = _row["ReportScheduleId"].ToString();
                al.Frequency = _row["Frequency"].ToString();
                al.ColcoContactTelephone = _row["ColcoContactTelephone"].ToString();

                list.Add(al);
            }
        }
        // aq = Populatereport(Dts.Variables["vnSource_SQL_Result"].Value);
        env = PopulateEnvironment(Dts.Variables["vnEnvironment"].Value);
        aq = list;


        paramval = new ParameterValue[2];
        paramval[0] = new ParameterValue();
        paramval[0].Name = "PRM_CustomerDetails";
        paramval[0].Value = aq[0].AccountNumber;
        paramval[1] = new ParameterValue();
        paramval[1].Name = "PRM_Startdate";
        paramval[1].Value = aq[0].StartDate;


        //Rendering the report begins

        ReportExecutionService rs = new ReportExecutionService();
        rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
        rs.Url = env.SSRSServerUrl.ToString();


        //Load the report options
        rs.LoadReport(aq[0].ReportPath, null);
        rs.SetExecutionParameters(paramval, aq[0].CultureCode);



        // Set the filename

        String filename = aq[0]. Number + "_" + env.Code + "_" + "_" + aq[0].Name +
            DateTime.UtcNow.ToString("_dd-MM-yyyy_hh-mm-ss.fff");

        //Render the report and generate pdf
        Byte[] results;
        string encoding = String.Empty;
        string mimeType = String.Empty;
        string extension = String.Empty;
        Warning[] warnings = null;
        string[] streamIDs = null;
        string deviceInfo = null;
        results = rs.Render(aq[0].ReportFormat, deviceInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);


        //Write the file into the directory
        using (FileStream stream = File.OpenWrite(@env.wipPath + filename))
        {

            stream.Write(results, 0, results.Length);
         }


            if (SendEmail(env.From, aq[0].To,  env.Subject, aq[0].Attachment, env.Server, false,  filename, env.TimeOut) == true)
            {
                // Move report file from WIP to Processed
                File.Move(@env.oldPath + filename, @env.newPath + filename);
                }


            }

2 个答案:

答案 0 :(得分:0)

您无需再做任何事情。通过调用QueueUserWorkItem,您说要在线程池管理的线程中执行give方法。但是,您无法保证它将立即执行,而且它是线程池的工作方式。当线程池线程可用时,将执行您的方法。

在代码的第一行,您调用ThreadPool.SetMaxThreads(6, 6);因为不会有超过6个线程池线程同时处于活动状态。在线程池中执行超出此限制的所有请求将排队。所以,也许你提出了很多要求,其中一些人只是在等待轮到他们了。

此外,您必须记住,可能还有另一个代码也使用线程池。在这种情况下,您的请求需要竞争线程池线程。

更新(讨论后):

尝试在process方法中放置断点。调试器将停在那里,它将证明process方法确实已执行。但是,您的代码中可能存在一些错误,这就是您没有看到设置电子邮件的原因

答案 1 :(得分:0)

我认为您的代码可能无法执行的一个原因是您在执行的线程和程序结束之间有某种race condition。你的代码有多长?如果你刚刚开始学习C#,我觉得你正在编写一个控制台应用程序,你的代码主要是Main()方法,并且包含几行代码。如果您在短应用程序上执行ThreadPool.QueueUserWorkItem()并立即到达Main()方法的末尾,则您的代码可能永远不会执行!

为了避免这种情况,您可以在Main()方法结束之前添加一个休眠时间,例如:

Thread.Sleep(1000);