web-dev-qa-db-ja.com

10分のトランザクションスコープタイムアウト

C#でTransactionScopeが長時間実行されています。スコープに長いタイムスパンが必要であることを伝えましたが、それでもタイムアウトが発生します。何がこれを引き起こす可能性がありますか?

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

こんにちは、web.configまたはapp.configにこのセクションがない場合は、構成ファイルでmaxTimeoutを確認できます

Machine.configを確認します

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

値を調整する

19
Aghilas Yakoub

さらに明確にするために:

トランザクションスコープは、最大タイムアウトとしてマシン構成設定を使用します。デフォルトのマシンタイムアウトは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オブジェクトには、タイムアウトを指定できるコンストラクターオーバーロードがありますが、その処理方法はわかりません。

33
Eric Schneider

Machine.configを変更せずにトランザクションに10分以上かかるようにするには、このコードを使用します

    private void SetTransactionManagerField(string fieldName, object value)
    {
        typeof(TransactionManager).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static).SetValue(null, value);
    }

    public TransactionScope CreateTransactionScope(TimeSpan timeout)
    {
        SetTransactionManagerField("_cachedMaxTimeout", true);
        SetTransactionManagerField("_maximumTimeout", timeout);
        return new TransactionScope(TransactionScopeOption.RequiresNew, timeout);
    }

使用法:

using (var ts = CreateTransactionScope(TimeSpan.FromMinutes(20)))
{ 
    DoLongCode();
    ts.Complete();
}

この記事に基づく記事のコードはもともとここに貼り付けられていました。回答のコードは、リファクタリングおよび簡素化されました。

23
Jupaol

タイムアウトを変更しようとしているコンテキストが間違っているため、機能しません。

有効なクエリに近い値に変更してください。

次のコンテキストが必要です。

    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
5
Fabio Guerrazzi

完全な信頼環境を考慮すると、リフレクションを使用して最大タイムアウトをオーバーライドできます。

            //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
                //...
            }

物理ファイルmachine.configを変更してこの問題を解決します。


1。ファイルをローカライズする必要があります:

  • 2ビット: 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>
1

このコードをプロジェクトに追加して、トランザクション時間を延長できます。

// 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));
0
Mantu