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

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)
    {
        // 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

「物理ファイル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 に答える
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 に答える