37

TransactionScope在 C# 中运行了很长时间。我告诉示波器它应该有很长的时间跨度,但我仍然超时。什么可能导致这种情况?

TransactionOptions transactionOptions = new TransactionOptions();
transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
transactionOptions.Timeout = TimeSpan.MaxValue;
using (var ts = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
{ 
    DoLongCode();
}
4

8 回答 8

40

要让交易时间超过 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();
}

基于这篇文章文章 的代码最初粘贴在这里。答案中的代码现在被重构和简化。

于 2015-03-03T23:45:57.300 回答
39

进一步澄清:

事务范围使用机器配置设置作为最大超时。默认机器超时为 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 对象还具有构造函数重载,允许您指定超时,但我不确定如何处理。

于 2012-10-17T19:29:09.097 回答
26

您好,如果您的 web.config 或 app.config 中没有此部分,您可以在配置文件中验证 maxTimeout

验证您的 machine.config

<configuration> 
  <system.transactions>
    <machineSettings maxTimeout=""/>
  </system.transactions>
</configuration> 

调整值

于 2012-08-21T13:10:53.947 回答
6

它们不起作用,因为您尝试更改超时的上下文错误。

尝试将其更改为更接近有效查询。

你应该有这些上下文:

    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
于 2015-10-18T19:16:58.363 回答
3

考虑到完全信任的环境,您可以使用反射覆盖最大超时:

            //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
                //...
            }
于 2014-11-11T13:29:33.597 回答
3

我通过修改“物理文件machine.config解决了这个问题。


1.您必须本地化文件:

  • 32 位: C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machie.config
  • 64 位: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config

2.您必须添加以下代码:

<system.transactions>
     <defaultSettings timeout="00:59:00" />
</system.transactions>
于 2016-07-01T20:45:56.663 回答
1

如果有人想知道如何在 .NET Core 上实现这一点, 这就是答案。基本上,您必须更新字段的名称:

_cachedMaxTimeout->s_cachedMaxTimeout

_maximumTimeout->s_maximumTimeout

于 2021-08-23T17:21:59.550 回答
0

您可以在您的项目中添加此代码以延长交易时间。

// 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));
于 2018-07-04T08:10:33.747 回答