我在 C# 中运行了很长时间
TransactionScope
。我告诉示波器它应该有很长的时间跨度,但我仍然超时。这可能是什么原因造成的?
TransactionOptions transactionOptions = new TransactionOptions();
transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
transactionOptions.Timeout = TimeSpan.MaxValue;
using (var ts = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
{
DoLongCode();
}
要允许交易时间超过10分钟,而不需要更改machine.config,请使用此代码
private void SetTransactionManagerField(string fieldName, object value)
{
typeof(TransactionManager).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static).SetValue(null, value);
}
public TransactionScope CreateTransactionScope(TimeSpan timeout)
{
// or for netcore / .net5+ use these names instead:
// s_cachedMaxTimeout
// s_maximumTimeout
SetTransactionManagerField("_cachedMaxTimeout", true);
SetTransactionManagerField("_maximumTimeout", timeout);
return new TransactionScope(TransactionScopeOption.RequiresNew, timeout);
}
用途:
using (var ts = CreateTransactionScope(TimeSpan.FromMinutes(20)))
{
DoLongCode();
ts.Complete();
}
基于本文 文章代码原贴在这里。答案中的代码现已重构和简化。
进一步澄清:
事务范围使用机器配置设置作为最大超时。 默认机器超时为 10 分钟。
将机器配置设置为 2 小时:
<system.transactions>
<machineSettings maxTimeout="02:00:00"/>
</system.transactions>
app.config 或 web.config 的使用时间可以缩短至超时时间,但不能超过机器配置超时时间。
将应用程序配置设置为 1 小时:
<system.transactions>
<defaultSettings timeout="01:00:00" />
</system.transactions>
此外,当达到限制时,我们没有收到任何异常,也没有跟踪或事件日志记录。
TransactionScope 对象还具有构造函数重载,允许您指定超时,但我不确定如何处理。
您好,如果您的 web.config 或 app.config 中没有此部分,您可以在配置文件中验证 maxTimeout
验证您的机器配置
<configuration>
<system.transactions>
<machineSettings maxTimeout=""/>
</system.transactions>
</configuration>
调整数值
它们不起作用,因为您尝试更改超时的上下文是错误的。
尝试将其更改为更接近有效查询。
您应该具备以下背景:
using (var txn = new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted, Timeout = new TimeSpan(1,0,0) })) // 1 hour or wathever, will not affect anything
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
int ct = connection.ConnectionTimeout // (read Only, this is the effective default timeout is 15 seconds)
connection.Open();
SqlCommand select = new SqlCommand(sql.query, connection); // bind to server
select.CommandTimeout = 0; // <-- here does apply infinite timeout
SqlDataReader reader = select.ExecuteReader(); // never stop
我通过修改“物理文件”machine.config解决了这个问题。
1. 您必须本地化文件:
2. 您必须添加以下代码:
<system.transactions>
<defaultSettings timeout="00:59:00" />
</system.transactions>
考虑到完全信任的环境,您可以使用反射覆盖最大超时:
//Get machineSettings session
var machineSettings = (System.Transactions.Configuration.MachineSettingsSection)ConfigurationManager.GetSection("system.transactions/machineSettings");
//Allow modifications
var bReadOnly = (typeof(ConfigurationElement)).GetField("_bReadOnly", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
bReadOnly.SetValue(machineSettings, false);
//Change max allowed timeout
machineSettings.MaxTimeout = TimeSpan.MaxValue;
using (var t = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(1,0,0))) { //1 hour transaction
//...
}
如果有人想知道如何在 .NET Core 上实现这一点, 这就是答案。基本上,您必须更新字段的名称:
_cachedMaxTimeout
-> s_cachedMaxTimeout
_maximumTimeout
-> s_maximumTimeout
您可以在您的项目中添加此代码来延长交易时间。
// This is used for set the transaction timeout to 40 minutes.
Type oSystemType = typeof(global::System.Transactions.TransactionManager);
System.Reflection.FieldInfo oCachedMaxTimeout =
oSystemType.GetField("_cachedMaxTimeout",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Static);
System.Reflection.FieldInfo oMaximumTimeout =
oSystemType.GetField("_maximumTimeout",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Static);
oCachedMaxTimeout.SetValue(null, true);
oMaximumTimeout.SetValue(null, TimeSpan.FromSeconds(2400));
TransactionScope 有多个构造函数。其中一些允许您更改超时而无需更改配置。
using (var scope = new TransactionScope(new TransactionScopeOption(), TimeSpan.FromMinutes(3), TransactionScopeAsyncFlowOption.Enabled))
{
// Long operation here
scope.Complete();
}
在 .NETCore(在 NET6 中测试)中,您不需要更改机器配置或使用反射。
你可以写:
TransactionManager.MaximumTimeout = TimeSpan.FromMinutes(60);
超时一小时。