我正在创建一个.net应用程序,该应用程序从表中检索查询,并从查询中获取数据并导出到excel文件。我有一个前端Web应用程序,用户可以在其中请求报告。当用户请求报告时,报告查询将保存在队列表中,并可供处理请求的.net应用程序使用。
我已经设置了一个测试应用程序,该应用程序可以将x个查询存储到一个数组中,然后创建任务以运行那些查询。
我的问题是:我想一次最多运行10个任务,每次完成一个任务,我都想创建一个新任务。
一些需要运行的报告可能需要20分钟。在创建一批新的10项任务之前,我不想等待缓慢的报告完成。
我在下面包含了我的代码。我似乎无法弄清楚在其他任务仍在运行时如何创建其他任务。
我在下面列出了完整的解决方案。如果有请求,并且当前正在运行<10个任务,则该应用程序将继续运行并添加新任务。
using System;
using System.Data;
using System.Data.Odbc;
using Excel = Microsoft.Office.Interop.Excel;
using System.Threading;
using System.Threading.Tasks;
namespace NetReports_Scheduler
{
class Program
{
public static String connectionString = @"dsn=EIS;Integrated Security=SSPI;";
public static int taskCounter = 0;
public static int maxTaskCount = 10;
public static int fileCounter = 1;
static void Main(string[] args)
{
RunProcess();
}
static private void RunProcess()
{
string[] queryData = new string[3];
var queryString = "";
var rowId = "";
var reportId = "";
queryData = CheckForNewRequest();
queryString = queryData[0];
rowId = queryData[1];
reportId = queryData[2];
if ((queryString != null) && (taskCounter < maxTaskCount))
{
String fileName = "Report_" + rowId + "_" + reportId + ".xlsx";
var excelFileName = @"C:\exportTest\" + fileName;
addNewTask(queryString, excelFileName, rowId);
}else{
System.Threading.Thread.Sleep(10000);
}
RunProcess();
}
private static string[] CheckForNewRequest()
{
string query = "";
string[] queryData = new string[3];
query = "SELECT TOP 1 [query_string], [rowId], [ReportId] FROM [HIPAA].[dbo].[tbl_NetReports_Scheduled_Queue] with (nolock) WHERE run_status = 0";
OdbcCommand command = new OdbcCommand(query);
using (OdbcConnection connection = new OdbcConnection(connectionString))
{
command.Connection = connection;
command.CommandTimeout = 0;
connection.Open();
try
{
OdbcDataReader myReader = command.ExecuteReader();
if (myReader.HasRows)
{
while (myReader.Read())
{
queryData[0] = myReader.GetString(0);
queryData[1] = myReader.GetString(1);
queryData[2] = myReader.GetString(2);
}
}
else
{
return queryData;
}
myReader.Close();
}
catch (Exception ex)
{
Console.WriteLine("Error" + ex.ToString());
}
return queryData;
}
}
static private void addNewTask(String query, String fileName, String rowId)
{
Task t = Task.Run(() =>
{
UpdateQueueStatus(rowId, 1,"start");
RunReport(query, fileName, rowId);
});
taskCounter += 1;
}
static private void UpdateQueueStatus(string rowId, int run_status, string update_type)
{
var sqlString = "";
DateTime date = DateTime.Now; // will give the date for today
if (update_type == "start")
{
sqlString = "UPDATE [HIPAA].[dbo].[tbl_NetReports_Scheduled_Queue] SET run_status = " + run_status + ", ";
sqlString += "start_run_date = '" + date + "' ";
sqlString += "WHERE rowId = " + rowId;
}
if (update_type == "end")
{
sqlString = "UPDATE [HIPAA].[dbo].[tbl_NetReports_Scheduled_Queue] SET run_status = " + run_status + ", ";
sqlString += "end_run_date = '" + date + "' ";
sqlString += "WHERE rowId = " + rowId;
}
OdbcCommand command = new OdbcCommand(sqlString);
using (OdbcConnection connection = new OdbcConnection(connectionString))
{
try
{
command.Connection = connection;
command.CommandTimeout = 0;
connection.Open();
command.ExecuteNonQuery();
taskCounter -= 1;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
static private void RunReport(string sqlString, string excelFileName, string rowId)
{
OdbcCommand command = new OdbcCommand(sqlString);
using (OdbcConnection connection = new OdbcConnection(connectionString))
{
command.Connection = connection;
command.CommandTimeout = 0;
connection.Open();
try
{
OdbcDataReader myReader = command.ExecuteReader();
DataTable reportdt = new DataTable();
reportdt.Load(myReader);
Excel.Application application = new Excel.Application();
Excel.Workbook workbook = application.Workbooks.Add();
Excel.Worksheet worksheet = workbook.Sheets[1];
var columns = reportdt.Columns.Count;
var rows = reportdt.Rows.Count;
if (rows == 0)
{
Console.WriteLine("No rows found");
}
else
{
var columnCount = 1;
foreach (DataColumn dc in reportdt.Columns)
{
worksheet.Cells[1, columnCount] = dc.ToString();
columnCount++;
}
Excel.Range range = worksheet.Range["A2", String.Format("{0}{1}", GetExcelColumnName(columns), rows)];
object[,] data = new object[rows, columns];
for (int rowNumber = 0; rowNumber < rows; rowNumber++)
{
for (int columnNumber = 0; columnNumber < columns; columnNumber++)
{
data[rowNumber, columnNumber] = reportdt.Rows[rowNumber][columnNumber].ToString();
}
}
range.Value = data;
workbook.SaveAs(excelFileName);
UpdateQueueStatus(rowId, 2, "end");
}
workbook.Close();
}
catch (Exception ex)
{
Console.WriteLine("Error with query" + ex.ToString());
Console.ReadLine();
}
// The connection is automatically closed at
// the end of the Using block.
}
}
private static string GetExcelColumnName(int columnNumber)
{
int dividend = columnNumber;
string columnName = String.Empty;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
dividend = (int)((dividend - modulo) / 26);
}
return columnName;
}
}
}