Если вы переключитесь на TemplateField
, вы можете сделать это встроенным.
<asp:TemplateField HeaderText="BankAcc">
<ItemTemplate>
<%# string.IsNullOrEmpty(Eval("HiddenBankAcc").ToString()) ? Eval("FullBankAcc") : Eval("HiddenBankAcc")%>
</ItemTemplate>
</asp:TemplateField>
Или как логическое значение
<asp:TemplateField HeaderText="BankAcc">
<ItemTemplate>
<%# Convert.ToBoolean(Eval("FullBankAcc")) ? Eval("FullBankAcc") : Eval("HiddenBankAcc")%>
</ItemTemplate>
</asp:TemplateField>
В целом да это будет работать. Однако дьявол находится в деталях.
Во-первых Вы хотите закрыть взаимное исключение в finally
блок. Иначе Ваш процесс мог резко завершить и оставить его в сообщенном состоянии, как исключение. Это сделало бы его так, чтобы будущие экземпляры процесса не были в состоянии запустить.
, К сожалению, хотя, даже с finally
блок необходимо иметь дело с потенциалом, что процесс будет завершен, не освобождая взаимное исключение. Это может произойти, например, если пользователь уничтожает процесс через TaskManager. Существует состояние состязания в Вашем коде, который позволил бы, чтобы второй процесс добрался AbandonedMutexException
в эти WaitOne
вызов. Вам будет нужна стратегия восстановления этого.
я поощряю Вас читать на детали Взаимоисключающего класса . Используя его не всегда просто.
<час>Подробно останавливающийся на возможности состояния состязания:
следующая последовательность событий может произойти, который заставил бы второй экземпляр приложения бросать:
WaitOne
вызов. AbanonedMutexException
. Это более обычно и удобно использовать события Windows с этой целью. Например,
static EventWaitHandle s_event ;
bool created ;
s_event = new EventWaitHandle (false,
EventResetMode.ManualReset, "my program#startup", out created) ;
if (created) Launch () ;
else Exit () ;
, Когда Ваш процесс выходит или завершается, Windows закроет событие для Вас и уничтожит его, если никакие открытые дескрипторы не останутся.
Добавленный : для управления сессиями используйте Local\
и Global\
префиксы для события (или взаимное исключение) имя. Если Ваше приложение в расчете на пользователя, просто добавьте имя соответственно искаженного зарегистрированного пользователя к имени события.
Можно использовать взаимное исключение, но сначала удостовериться, что это действительно, что Вы хотите.
, поскольку "предотвращение нескольких экземпляров" ясно не определяется. Это может означать
При помощи взаимного исключения, Вы в основном используете определить номер 4.
В Windows, завершая процесс имеет следующие результаты:
Взаимоисключающие объекты являются объектами ядра, таким образом, любой сохраненный процессом закрывается, когда процесс завершается (в Windows так или иначе).
, Но, отметьте следующий бит в CreateMutex () документы:
, Если Вы используете именованное взаимное исключение для ограничения приложения единственным экземпляром, злонамеренный пользователь может создать это взаимное исключение, прежде чем Вы будете делать и будете препятствовать тому, чтобы Ваше приложение запустилось.
Да, это безопасно, я предложил бы следующий шаблон, потому что необходимо удостовериться, что эти Mutex
всегда выпускается.
using( Mutex mutex = new Mutex( false, "mutex name" ) )
{
if( !mutex.WaitOne( 0, true ) )
{
MessageBox.Show("Unable to run multiple instances of this program.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
Если Вы хотите использовать основанный на взаимном исключении подход, необходимо действительно использовать локальное взаимное исключение для , ограничивают подход только к сессии входа в систему текущего пользователя . И также отметьте другой важный протест в той ссылке об устойчивом распоряжении ресурса со взаимоисключающим подходом.
Один протест состоит в том, что основанный на взаимном исключении подход не позволяет Вам активировать первую инстанцию приложения, когда пользователь пытается запустить второй экземпляр.
альтернатива к PInvoke к FindWindow, сопровождаемому SetForegroundWindow на первой инстанции. Другая альтернатива должна проверить на Ваш процесс по имени:
Process[] processes = Process.GetProcessesByName("MyApp");
if (processes.Length != 1)
{
return;
}
Обе из этих последних альтернатив имеют гипотетическое состояние состязания, где два экземпляра приложения могли быть запущены одновременно и затем обнаружить друг друга. Это вряд ли произойдет на практике - на самом деле, во время тестирования, я не мог заставить его произойти.
Другая проблема с этими двумя последними альтернативами - то, что они не будут работать при использовании Служб удаленных рабочих столов.
Я использую этот метод, я считаю, что он быть в безопасности, потому что мьютекс уничтожается, если он долго не удерживается каким-либо приложением (и приложения завершаются, если они не могут изначально создать мьютекст). Это может или не может работать идентично в «процессах AppDomain» (см. Ссылку внизу):
// Make sure that appMutex has the lifetime of the code to guard --
// you must keep it from being collected (and the finalizer called, which
// will release the mutex, which is not good here!).
// You can also poke the mutex later.
Mutex appMutex;
// In some startup/initialization code
bool createdNew;
appMutex = new Mutex(true, "mutexname", out createdNew);
if (!createdNew) {
// The mutex already existed - exit application.
// Windows will release the resources for the process and the
// mutex will go away when no process has it open.
// Processes are much more cleaned-up after than threads :)
} else {
// win \o/
}
Вышесказанное страдает от примечаний в других ответах / комментариях о том, что вредоносные программы могут сидеть на мьютексе. Здесь не проблема. Кроме того, мьютекс без префикса создается в «локальном» пространстве. Наверное, здесь все правильно.
См .: http://ayende.com/Blog/archive/2008/02/28/The-mysterious-life-of-mutexes.aspx - поставляется с Джоном Скитом; -)