private void Terminate(IAsyncPropertySheet Aps)
{
Aps.Event.WaitOne();
}
используется так:
IAsyncPropertySheet aps = propSheet as IAsyncPropertySheet;
if (m_IsLastSheet m_SingleSheet)
if(aps == null)
DialogResult = DialogResult.OK;
else
{
btnNext.Enabled = false;
btnPrev.Enabled = false;
OneParamDelegate terminate = Terminate;
terminate.BeginInvoke(aps, Callback, null);
}
а Callback выглядит проще некуда
private void Callback(IAsyncResult ar)
{
InnerHide();
DialogResult = DialogResult.OK;
}
void InnerHide()
{
if (InvokeRequired)
{
ParameterlessDelegate del = InnerHide;
Invoke(del);
}
else
Hide();
}
Другими словами, форма не будет закрыта, пока событие интерфейса, реализуемого страницей свойств, не будет установлено в signaled: какой-то полезный код работает на странице и когда отработает, установит событие, по которому форма и закроется. Дёшево и сердито. На всякий случай, чтобы не было недосказанностей, вот событие, используемое для закрытия
public ManualResetEvent Event
{
get {return (Exporter as IAsyncExecution).Event;}
}
при этом Exporter, само собой, инициализируется в конструкторе. Класс, реализующий IAsyncExecution, выглядит так:
public class InternalYYYFactory: Notifier, IExport, IExportInitializer, IAsyncExecution
{
private ManualResetEvent m_Event = new ManualResetEvent(false);
...
public ulong ExportPacket(string FullPath, global::XXXX.YYY Yyy)
{
NotifyOwner(this, 1, "Инициализация файла");
using(FileStream fs = new FileStream(FullPath, FileMode.Create, FileAccess.ReadWrite))
{
Request req;
NotifyOwner(this, 50, "Запись пакета");
new XmlSerializer(typeof(Request)).Serialize(fs, req = GetYyy(Yyy));
NotifyOwner(this, 100, "Запись завершена");
if (Abyr(Yyy))
{
m_Callback(m_PacketNumber = req.packetHeader.id);
m_Event.Set();
return m_PacketNumber;
}
m_Event.Set();
}
return 0;
}
Так вот, 949 говорит о том, что на выделенной жирным строке форма просто исчезает. При том, что никаких чудес в рассылке уведомлений нет:
public class Notifier
{
private int m_CurrentPercentage;
public event ExportProgressHandler ExportProgress;
protected void NotifyOwner(IExport This, int Percentage, string Text)
{
if (ExportProgress != null)
ExportProgress(This, new ExportEventArgs(m_CurrentPercentage = Percentage, Text));
}
protected void NotifyOwner(IExport This, Inc Increment, string Text)
{
NotifyOwner(This, m_CurrentPercentage + Increment.Value, Text);
}
}
Нет соображений? Не было их и у меня, особенно, если добавить к №949 №954. Интересно

и то, что эффект зависел от того, на каком компьютере это собирается (у нас идёт замена железок, сам чёрт сломит...). Мне пришлось разбираться. Самопроизвольное закрытие формы могло быть только в случае установки события в true, но код явно инициализирует его в false. В общем, добавил в Terminate простую диагностику: вывод в лог. Больше ничего не трогал. Собрали на проблемном компьютере - проблемы ушли. И 949 и 954. Цирк? Цирк! И никому не предъявишь. Сейчас вспомнил, что было похожее в VS2003 в статических классах, когда переменная инициализировалась вне статического конструктора. По стандарту это разрешалось, а фактически - переменная получала значение по умолчанию вне зависимости от того, что было написано в инициализаторе. Вот так то. Лучшее средство разработки для .NET. 12 часов долой. Конечно, у нас же их бессчётно.