NET 核心后台服务:"A task was canceled." 错误
NET Core BackgroundService: "A task was canceled." Error
你好,我开发了 BackgroundService,它用于监视 Oracle 数据库,当新记录插入源 table 时,将记录复制到 SQL 服务器数据库。但过了一段时间(有时 1 天,有时 2 天)。我的服务已停止工作。错误说:“任务已取消”。我不明白为什么我的代码突然停止工作。
注意: 我的应用程序托管在 IIS 上(Windows Server 2012)
- 我想运行我的申请没完没了。
这是我的代码:
public class MainTransactionService : BackgroundService
{
private readonly ILogger Logger;
private readonly TransactionSettings TSettings;
public MainTransactionService(ILogger logger, TransactionSettings tSettings)
{
TSettings = tSettings;
Logger = logger;
}
protected async override Task ExecuteAsync(CancellationToken stoppingToken)
{
//Create a connection to Oracle
string conString = "";
//How to connect to an Oracle DB without SQL*Net configuration file
// also known as tnsnames.ora.
//"Data Source=orclpdb";
"Data Source=eoffice";
OracleConfiguration.OracleDataSources.Add("eoffice", "");
//How to connect to an Oracle DB with a DB alias.
//Uncomment below and comment above.
//"Data Source=<service name alias>;";
OracleConnection con = new OracleConnection(conString);
Logger.Information("Connected to Oracle");
OracleCommand cmd = con.CreateCommand();
try
{
Logger.Information("Run part executed");
if (con.State != ConnectionState.Open)
{
con.Open();
}
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(TSettings.Frequency, stoppingToken);
//Logger.Information(stoppingToken.IsCancellationRequested.ToString());
try
{
var cancelTask = Task.Delay(TSettings.Timeout, stoppingToken);
//Logger.Information("CODE EXECUTED");
//await context.Response.WriteAsync("Server is Listening");
//OracleConfiguration.OracleDataSources.Add("orclpdb", "(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = miatdw1.miat.com.mn)(PORT = 1521)))(CONNECT_DATA = (SERVICE_NAME = orclpdb.miat.com.mn)))");
//Check Oracle
Logger.Information("Establishing Oracle Connection (While)");
cmd.CommandText = "select MAX(id) from PB_TRANSACTION";
int SourceTableMaxId = Convert.ToInt32(cmd.ExecuteScalar());
//Check SQL
SqlConnection conn = new SqlConnection("");
SqlCommand check_id = new SqlCommand("select MAX(id) from PB_TRANSACTION", conn);
Logger.Information("Establishing MS-SQL Connection");
conn.Open();
int TargetTableMaxId = Convert.ToInt32(check_id.ExecuteScalar());
if (SourceTableMaxId > TargetTableMaxId)
{
int TotalNewRecords = SourceTableMaxId - TargetTableMaxId;
Logger.Information(TotalNewRecords.ToString() + " New Records Found");
OracleCommand command = new OracleCommand();
command.CommandText = "select * from (select * from pb_transaction order by id desc) x where ROWNUM <= :lastrecord";
command.Parameters.Add(":username", OracleDbType.Int32).Value = TotalNewRecords;
command.Connection = con;
Logger.Information("Retrieved " + TotalNewRecords.ToString() + " from PB_TRANSACTION table.");
Transaction LastTransaction = new Transaction();
using (OracleDataReader oReader = command.ExecuteReader())
{
while (oReader.Read())
{
LastTransaction.Id = Convert.ToInt32(oReader["ID"]);
LastTransaction.type = oReader["TYPE"].ToString();
LastTransaction.account = oReader["ACCOUNT"].ToString();
LastTransaction.journal_id = oReader["JOURNAL_ID"].ToString();
LastTransaction.amount = Convert.ToDouble(oReader["AMOUNT"]);
LastTransaction.currency = oReader["CURRENCY"].ToString();
LastTransaction.posted_date = oReader["POSTED_DATE"].ToString();
LastTransaction.statement_date = oReader["STATEMENT_DATE"].ToString();
LastTransaction.description = oReader["DESCRIPTION"].ToString();
LastTransaction.pnr = oReader["PNR"].ToString();
LastTransaction.pnr_approved = Convert.ToInt32(oReader["PNR_APPROVED"]);
LastTransaction.jid = oReader["JID"].ToString();
LastTransaction.user_id = oReader["USER_ID"].ToString();
LastTransaction.inserted_date = oReader["INSERTED_DATE"].ToString();
SqlCommand scmd = new SqlCommand("insert into PB_TRANSACTION (ID,TYPE, ACCOUNT, JOURNAL_ID, AMOUNT, CURRENCY, POSTED_DATE, STATEMENT_DATE, DESCRIPTION, PNR, PNR_APPROVED, JID, USER_ID, INSERTED_DATE) values(@id,@type,@account,@journalid, @amount,@currency,@posteddate,@statementdate,@description,@pnr,@pnrapproved,@jid,@userid,@inserteddate);", conn);
scmd.Parameters.AddWithValue("@id", LastTransaction.Id);
scmd.Parameters.AddWithValue("@type", LastTransaction.type);
scmd.Parameters.AddWithValue("@account", LastTransaction.account);
scmd.Parameters.AddWithValue("@journalid", LastTransaction.journal_id);
scmd.Parameters.AddWithValue("@amount", LastTransaction.amount);
scmd.Parameters.AddWithValue("@currency", LastTransaction.currency);
scmd.Parameters.AddWithValue("@posteddate", LastTransaction.posted_date);
scmd.Parameters.AddWithValue("@statementdate", LastTransaction.statement_date);
scmd.Parameters.AddWithValue("@description", LastTransaction.description);
scmd.Parameters.AddWithValue("@pnr", LastTransaction.pnr);
scmd.Parameters.AddWithValue("@pnrapproved", LastTransaction.pnr_approved);
scmd.Parameters.AddWithValue("@jid", LastTransaction.jid);
scmd.Parameters.AddWithValue("@userid", LastTransaction.user_id);
scmd.Parameters.AddWithValue("@inserteddate", LastTransaction.inserted_date);
scmd.ExecuteNonQuery();
}
Logger.Information(TotalNewRecords.ToString() + " records inserted");
}
}
else
{
Logger.Information("No New Records found");
}
}
catch (Exception ex)
{
LogError("INNER TRY: " + ex.Message);
}
}
Logger.Information("Oracle Database connection has successfully Disconnected!!!");
}
catch (TaskCanceledException tex)
{
LogError("TASK ERROR: " + tex.Message);
}
catch (Exception ex)
{
LogError("MAIN ERROR: " + ex.Message);
}
finally
{
con.Close();
con.Dispose();
}
}
public async override Task StopAsync(CancellationToken cancellationToken)
{
await base.StopAsync(cancellationToken);
}
private void LogError(string error)
{
Logger.Error(error);
}
}
my application hosting on IIS (Windows Server 2012)
I want to run my application endlessly.
在 IIS 的 ASP.NET 中托管的 BackgroundService
将 运行 只要您的 ASP.NET 应用程序 运行。而已。由于 ASP.NET/IIS 会定期重新启动,您的 BackgroundService
将定期关闭(并重新启动)。 ASP.NET 和 IIS 都不是为 long-lived 后台进程设计的;它们是为 HTTP 服务设计的。在一般情况下(即云提供商),您的应用实际上可能会关闭,直到下一个 HTTP 请求到来。
如果这不可接受,那么 ASP.NET/IIS 不是满足您需要的正确主机。您可以使用 Win32 服务主机而不是 ASP.NET/IIS,方法是使用 Worker Service 模板创建一个新项目,添加 Win32 服务生命周期,并在该应用程序中托管相同的 BackgroundService
在您的 ASP.NET 应用中。
你好,我开发了 BackgroundService,它用于监视 Oracle 数据库,当新记录插入源 table 时,将记录复制到 SQL 服务器数据库。但过了一段时间(有时 1 天,有时 2 天)。我的服务已停止工作。错误说:“任务已取消”。我不明白为什么我的代码突然停止工作。
注意: 我的应用程序托管在 IIS 上(Windows Server 2012)
- 我想运行我的申请没完没了。
这是我的代码:
public class MainTransactionService : BackgroundService
{
private readonly ILogger Logger;
private readonly TransactionSettings TSettings;
public MainTransactionService(ILogger logger, TransactionSettings tSettings)
{
TSettings = tSettings;
Logger = logger;
}
protected async override Task ExecuteAsync(CancellationToken stoppingToken)
{
//Create a connection to Oracle
string conString = "";
//How to connect to an Oracle DB without SQL*Net configuration file
// also known as tnsnames.ora.
//"Data Source=orclpdb";
"Data Source=eoffice";
OracleConfiguration.OracleDataSources.Add("eoffice", "");
//How to connect to an Oracle DB with a DB alias.
//Uncomment below and comment above.
//"Data Source=<service name alias>;";
OracleConnection con = new OracleConnection(conString);
Logger.Information("Connected to Oracle");
OracleCommand cmd = con.CreateCommand();
try
{
Logger.Information("Run part executed");
if (con.State != ConnectionState.Open)
{
con.Open();
}
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(TSettings.Frequency, stoppingToken);
//Logger.Information(stoppingToken.IsCancellationRequested.ToString());
try
{
var cancelTask = Task.Delay(TSettings.Timeout, stoppingToken);
//Logger.Information("CODE EXECUTED");
//await context.Response.WriteAsync("Server is Listening");
//OracleConfiguration.OracleDataSources.Add("orclpdb", "(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = miatdw1.miat.com.mn)(PORT = 1521)))(CONNECT_DATA = (SERVICE_NAME = orclpdb.miat.com.mn)))");
//Check Oracle
Logger.Information("Establishing Oracle Connection (While)");
cmd.CommandText = "select MAX(id) from PB_TRANSACTION";
int SourceTableMaxId = Convert.ToInt32(cmd.ExecuteScalar());
//Check SQL
SqlConnection conn = new SqlConnection("");
SqlCommand check_id = new SqlCommand("select MAX(id) from PB_TRANSACTION", conn);
Logger.Information("Establishing MS-SQL Connection");
conn.Open();
int TargetTableMaxId = Convert.ToInt32(check_id.ExecuteScalar());
if (SourceTableMaxId > TargetTableMaxId)
{
int TotalNewRecords = SourceTableMaxId - TargetTableMaxId;
Logger.Information(TotalNewRecords.ToString() + " New Records Found");
OracleCommand command = new OracleCommand();
command.CommandText = "select * from (select * from pb_transaction order by id desc) x where ROWNUM <= :lastrecord";
command.Parameters.Add(":username", OracleDbType.Int32).Value = TotalNewRecords;
command.Connection = con;
Logger.Information("Retrieved " + TotalNewRecords.ToString() + " from PB_TRANSACTION table.");
Transaction LastTransaction = new Transaction();
using (OracleDataReader oReader = command.ExecuteReader())
{
while (oReader.Read())
{
LastTransaction.Id = Convert.ToInt32(oReader["ID"]);
LastTransaction.type = oReader["TYPE"].ToString();
LastTransaction.account = oReader["ACCOUNT"].ToString();
LastTransaction.journal_id = oReader["JOURNAL_ID"].ToString();
LastTransaction.amount = Convert.ToDouble(oReader["AMOUNT"]);
LastTransaction.currency = oReader["CURRENCY"].ToString();
LastTransaction.posted_date = oReader["POSTED_DATE"].ToString();
LastTransaction.statement_date = oReader["STATEMENT_DATE"].ToString();
LastTransaction.description = oReader["DESCRIPTION"].ToString();
LastTransaction.pnr = oReader["PNR"].ToString();
LastTransaction.pnr_approved = Convert.ToInt32(oReader["PNR_APPROVED"]);
LastTransaction.jid = oReader["JID"].ToString();
LastTransaction.user_id = oReader["USER_ID"].ToString();
LastTransaction.inserted_date = oReader["INSERTED_DATE"].ToString();
SqlCommand scmd = new SqlCommand("insert into PB_TRANSACTION (ID,TYPE, ACCOUNT, JOURNAL_ID, AMOUNT, CURRENCY, POSTED_DATE, STATEMENT_DATE, DESCRIPTION, PNR, PNR_APPROVED, JID, USER_ID, INSERTED_DATE) values(@id,@type,@account,@journalid, @amount,@currency,@posteddate,@statementdate,@description,@pnr,@pnrapproved,@jid,@userid,@inserteddate);", conn);
scmd.Parameters.AddWithValue("@id", LastTransaction.Id);
scmd.Parameters.AddWithValue("@type", LastTransaction.type);
scmd.Parameters.AddWithValue("@account", LastTransaction.account);
scmd.Parameters.AddWithValue("@journalid", LastTransaction.journal_id);
scmd.Parameters.AddWithValue("@amount", LastTransaction.amount);
scmd.Parameters.AddWithValue("@currency", LastTransaction.currency);
scmd.Parameters.AddWithValue("@posteddate", LastTransaction.posted_date);
scmd.Parameters.AddWithValue("@statementdate", LastTransaction.statement_date);
scmd.Parameters.AddWithValue("@description", LastTransaction.description);
scmd.Parameters.AddWithValue("@pnr", LastTransaction.pnr);
scmd.Parameters.AddWithValue("@pnrapproved", LastTransaction.pnr_approved);
scmd.Parameters.AddWithValue("@jid", LastTransaction.jid);
scmd.Parameters.AddWithValue("@userid", LastTransaction.user_id);
scmd.Parameters.AddWithValue("@inserteddate", LastTransaction.inserted_date);
scmd.ExecuteNonQuery();
}
Logger.Information(TotalNewRecords.ToString() + " records inserted");
}
}
else
{
Logger.Information("No New Records found");
}
}
catch (Exception ex)
{
LogError("INNER TRY: " + ex.Message);
}
}
Logger.Information("Oracle Database connection has successfully Disconnected!!!");
}
catch (TaskCanceledException tex)
{
LogError("TASK ERROR: " + tex.Message);
}
catch (Exception ex)
{
LogError("MAIN ERROR: " + ex.Message);
}
finally
{
con.Close();
con.Dispose();
}
}
public async override Task StopAsync(CancellationToken cancellationToken)
{
await base.StopAsync(cancellationToken);
}
private void LogError(string error)
{
Logger.Error(error);
}
}
my application hosting on IIS (Windows Server 2012)
I want to run my application endlessly.
在 IIS 的 ASP.NET 中托管的 BackgroundService
将 运行 只要您的 ASP.NET 应用程序 运行。而已。由于 ASP.NET/IIS 会定期重新启动,您的 BackgroundService
将定期关闭(并重新启动)。 ASP.NET 和 IIS 都不是为 long-lived 后台进程设计的;它们是为 HTTP 服务设计的。在一般情况下(即云提供商),您的应用实际上可能会关闭,直到下一个 HTTP 请求到来。
如果这不可接受,那么 ASP.NET/IIS 不是满足您需要的正确主机。您可以使用 Win32 服务主机而不是 ASP.NET/IIS,方法是使用 Worker Service 模板创建一个新项目,添加 Win32 服务生命周期,并在该应用程序中托管相同的 BackgroundService
在您的 ASP.NET 应用中。