Для программы создаётся расширение на .NET с использованием WinForms. Из этого расширение вызывается форма.
Проблема в том, что поток с виндоус очередью у основного приложения повисает. Как сделать, так чтобы у формы расширения был отдельный поток на обработку очереди сообщений?
И как его правильно потом остановить после отключения расширения?
UPD
Утрированный пример:
private void button1_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
form2.Show();
Thread.Sleep(1000 * 10); // что-то долго делает.
form2.Close();
}
Здесь требуется чтобы форма form2
нормально прорисовывалась и реагировала на действия пользователя, хотя при этом поток родительской формы виснет на обработке чего-нибудь.
Чтобы form2
работала в отдельном потоке независимо от родительской окна можно создать поток и установить у него апартаменты STA
. Из этом потока показываем form2
.
Основываясь на этом примере создаем класс второго потока:
(UPD по совету @PavelMayorov упрощаем реализацию)
class SecondWindowsThread : IDisposable
{
private SynchronizationContext ctx;
public SecondWindowsThread()
{
ManualResetEvent mre = new ManualResetEvent(false);
try
{
Thread thread = new Thread(
() =>
{
this.ctx = new WindowsFormsSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(this.ctx);
mre.Set();
Application.Run();
}
);
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
mre.WaitOne();
}
finally
{
mre.Dispose();
}
}
#region IDisposable Support
private bool disposedValue = false;
public void Dispose()
{
if (disposedValue) return;
if (this.ctx != null)
{
this.ctx.Send((_) => Application.ExitThread(), null);
this.ctx = null;
}
disposedValue = true;
}
#endregion
public SynchronizationContext SynchronizationContext
{
get
{
if (this.disposedValue) throw new ObjectDisposedException(nameof(SynchronizationContext));
return this.ctx;
}
}
}
Тогда обработчик кнопки будет такой:
private void button1_Click(object sender, EventArgs e)
{
Form2 form2 = null;
using (var t2 = new SecondWindowsThread())
{
t2.SynchronizationContext.Send(
(_) =>
{
form2 = new Form2();
form2.Show();
}, null);
Thread.Sleep(1000 * 10); // что-то долго делает.
t2.SynchronizationContext.Send((_) => form2.Close(), null);
}
}
При этом надо учитывать, что работать с компонентами одной формы из другой надо через синхронизирующий контекст или методы Control.Invoke, Control.BeginInvoke.
Лабораторная работа
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Во время работы, программа должна принимать AssetBundleAssetBundle должен содержать ImageTarget и контент, относящийся к нему
Решил сделать программку на шарпе для андроидДобавил в VS installer все инструменты для андроид розработки