Transaction scope timeout on 10 minutes
Solution 1
Hello you can verify maxTimeout in your config file, if you don't have this section on your web.config or app.config
Verify your machine.config
<configuration>
<system.transactions>
<machineSettings maxTimeout=""/>
</system.transactions>
</configuration>
Adjust the value
Solution 2
To allow transaction to take more than 10 minutes, without need to change machine.config, use this code
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);
}
Usage:
using (var ts = CreateTransactionScope(TimeSpan.FromMinutes(20)))
{
DoLongCode();
ts.Complete();
}
Based on this article The code of article was originally pasted here. The code in the answer is now refactored and simplified.
Solution 3
They dont' work because is the wrong context where you are trying to change timeout.
try to change it closer to the effective query.
You should have these contexts:
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
Solution 4
Considering a full trust environment, you can override max timeout using reflection:
//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
//...
}
Solution 5
I resolve this problem modifying the "physical file" machine.config.
1. You have to localize the file:
- 32 Bits: C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machie.config
- 64 Bits: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config
2. You have to add the following code:
<system.transactions>
<defaultSettings timeout="00:59:00" />
</system.transactions>
Patrick
Updated on November 18, 2021Comments
-
Patrick over 2 years
I have a long running
TransactionScope
in C#. I told the scope that it should have a long timespan, but still I get a timeout. What could cause this?TransactionOptions transactionOptions = new TransactionOptions(); transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted; transactionOptions.Timeout = TimeSpan.MaxValue; using (var ts = new TransactionScope(TransactionScopeOption.Required, transactionOptions)) { DoLongCode(); }
-
schglurps over 11 yearsIn Windows Azure this cannot be changed, 10 minutes is the maximum timeout.
-
Aghilas Yakoub over 11 yearsYes it's possible to override machine.config
-
jpierson over 11 yearsAccording to this thread on MSDN you cannot override the maxTimeout value in your web.config or app.config file. social.msdn.microsoft.com/Forums/da-DK/…
-
springy76 almost 10 years@jpierson I really hate Microsoft for this. Why should I change a system setting when there is just this single app which needs extraordinary behavior. Have they ever thought about exclusive mode local DBs like 'LocalDB', 'SQLCe', 'SQLite'? NO!
-
Maxim over 6 yearsPossible limitation: it should be called before any transaction (works fine in console, but not in web app).
-
martinoss over 4 yearsNot how I wished to implement it, but It's a solution and works for me (Azure WebJob)
-
Josh over 4 yearsI like this solution a lot as in many environments you have no access to the machine.config and this solution does work as intended.
-
Alan Fluka almost 4 yearsFor me, the fields were named s_cachedMaxTimeout and s_maximumTimeout, so I've changed it to try either field name and use what works. This is still pretty much a hack (as noted in the original article), but sometimes there really is no other option.
-
Gert Arnold over 3 yearsPlease... reflection should never be used to set inaccessible members because, basically, you don't know what you're doing. There are legal method to do what OP wants. Also, this is a repetition of an existing answer.
-
Gert Arnold over 3 yearsWhich perfectly demonstrates the problem with this hack. It breaks easily. This should never be used in production code. Who knows, in a next version these members may be completely gone and you have a big problem.
-
David Liebeherr almost 3 years@GertArnold I would generally agree that setting the value of a private member of a type that you do not own is a very bad idea. However I do not agree for this specific scenario. AFAIK the only officially supported way to increase the maximum for the transaction timeout is modifying the machine.config. However this is something we are all to often not allowed to do, because of the IT policies that are in place. Almost none of my customers would allow anyone to make such a change. Therefore using the mentioned hack is AFAIK the only possible alternative solution to this problem.
-
Gert Arnold almost 2 yearsEven then, it only repeats this answer.