Дано: 2 формы.
Главная форма содержит кнопку по которой вызывается второстепенная форма (форма 2).
Форма 2 содержит паузу System.Threading.Thread.Sleep(10000)
для имитации сложной работы (загрузки компонентов, множества изображений, отрисовки).
Задача: мгновенно отобразить форму 2 при нажатии кнопки на главной форме. При этом до нажатия кнопки, пользователь не должен видеть форму 2 (даже мелькающую). Кнопку пользователь нажмет не ранее, чем через 10 секунд после старта программы.
Я перепробовал варианты с запуском в другом потоке, пытался использовать просто Task
, BackgroundWorker
, ThreadPool
. Не получается, как правило проблема при вызове формы по второй кнопке.
Какие есть идея?
Один из примеров, как я пытался решить задачу:
private void Form1_Load(object sender, EventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (s, ea) =>
{
frm.Show();
// В форме 2 стоит this.Visible = false;
};
bw.RunWorkerAsync();
}
private void button1_Click(object sender, EventArgs e)
{
Console.WriteLine("button1_Click");
this.Invoke(new MethodInvoker(frm.ShowForm));
}
// Form 2:
public void ShowForm()
{
Console.WriteLine("Form2 showForm");
this.Visible = true;
this.WindowState = FormWindowState.Normal;
this.BringToFront();
}
Всю долгую логику надо засунуть в конструктор второй формы (это я думаю логично). А дальше при запуске первой, в отдельном потоке создать вторую форму. И оставить её в памяти. По клику по кнопке её просто показать. Что то вот в этом роде:
public partial class Form1 : Form
{
private Form2 _form;
public Form1()
{
InitializeComponent();
new Thread(()=>{_form = new Form2();}).Start();
}
private void button1_Click(object sender, EventArgs e)
{
_form.Show();
}
}
Единственная проблема данного кода, если пользователь нажмет кнопку ДО того как форма загрузится, все упадет. Но тут можно или просто проверять на Null, или использовать таски и проверять при нажатии кнопки что таска завершилась).
Поэтому не стоит делать вещи вроде Thread.Sleep()
. Не в коем случае не стоит в потоке UI вызывать вызывать методы (допустим SomeMethod(…)
) возвращающие Task<T>
, просто SomeMethod(…).Result
– это вызывает deadlock.
Допустим есть метод возвращающий JSON:
public static async Task<JObject> GetJsonAsync(Uri uri)
{
using (var client = new HttpClient())
{
var jsonString = await client.GetStringAsync(uri);
return JObject.Parse(jsonString);
}
}
Вот так делать неправильно, мы так получим deadlock.
private void Button1_Click(...)
{
var jsonTask = GetJsonAsync(...);
// Тут мы получаем deadlock
textBox1.Text = jsonTask.Result;
}
Вместо это правильно было бы сделать так:
public async void Button1_Click(...)
{
var json = await GetJsonAsync(...);
textBox1.Text = json;
}
Решаем задачи освобождения потока UI таким образом: добавляем модификатор async
к обработчику события (это Load
, Click
и т.д., в основном они получаются async void
). Далее внутри него выполняем какой-либо Task
с помощью await
.
Поэтому в итоге что-то получается вроде:
private async void Form_Load(object sender, EventArgs e)
{
await Task.Delay(10000); // Допустим сделаем ожидание 10 секунд
var r = await … // Некоторый Task<Result>;
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Есть стандарт IEEE 754 двоичного представления чисел и их арифметикиВ нем описываются нормализованные числа и ненормализованные
Возможно ли запустить программу командой через rdp или ssh зная ток имя файла, если да, то можно поподробнее?
Как вывести все подряд данные из таблицы в Unity? Есть такой код, но выдает ошибку: