Próbuję użyć wątków i zapobiec zamrożeniu programu, gdy wątek jest zajęty. Powinien pokazać postęp (pisanie 0/1), a nie tylko pokazać wynik po jego zakończeniu, zamrożenie formularza w międzyczasie.C# Gwintowanie za pomocą invoke, zamrożenie formularza
W bieżącym programie próbuję napisać do pola tekstowego, a faktycznie widzę stały postęp, a na formularzu nie mogą wpływać zadania drugiego wątku.
Co mam teraz, mogę napisać do pola tekstowego za pomocą wątku za pomocą invoke, ale pokazuje tylko wynik (Formularz zamarza, gdy wątek jest zajęty), a formularz zawiesza się.
Forma obrazu:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace MultiThreading
{
public partial class MultiThreading : Form
{
public MultiThreading()
{
InitializeComponent();
}
Thread writeOne, writeTwo;
private void writeText(TextBox textBox, string text)
{
if (textBox.InvokeRequired)
{
textBox.BeginInvoke((MethodInvoker)delegate()
{
for (int i = 0; i < 500; i++)
{
textBox.Text += text;
}
});
}
else
{
for (int i = 0; i < 500; i++)
{
textBox.Text += text;
}
}
}
private void btnWrite1_Click(object sender, EventArgs e)
{
writeOne = new Thread(() => writeText(txtOutput1, "0"));
writeOne.Start();
}
private void btnWrite2_Click(object sender, EventArgs e)
{
writeTwo = new Thread(() => writeText(txtOutput2, "1"));
writeTwo.Start();
}
private void btnClear1_Click(object sender, EventArgs e)
{
txtOutput1.Clear();
}
private void btnClear2_Click(object sender, EventArgs e)
{
txtOutput2.Clear();
}
private void btnWriteBoth_Click(object sender, EventArgs e)
{
writeOne = new Thread(() => writeText(txtOutput1, "0"));
writeTwo = new Thread(() => writeText(txtOutput2, "1"));
writeOne.Start();
writeTwo.Start();
}
private void btnClearBoth_Click(object sender, EventArgs e)
{
txtOutput1.Clear();
txtOutput2.Clear();
}
}
}
EDIT:
Btw dla każdego, zastanawiając się, jestem nowy na wielowątkowość i po prostu próbuję napisać mały program, aby zrozumieć najlepszy sposób na zrobienie tego.
Rozumiem, że moja poprzednia próba nie pomogła mi, ponieważ nadal nie dawałem formularza okazji do aktualizacji, więc do niego dotarłem.
OK, tak działa 1 wątek w ten sposób działa, ale nadal działa wiele wątków razem, nie zaktualizuje formularza, dopóki wątek nie zostanie ukończony.
Dodałem thread.sleep(), więc mogę spróbować wyczyścić podczas pisania, aby sprawdzić, czy nadal mogę korzystać z formularza.
Podczas pisania do 1 pola tekstowego nadal mogę wyczyścić ekran podczas pisania.
Ale kiedy używam 2 wątków, nie mogę już używać formularza do zakończenia wątku i daje dane wyjściowe.
private void writeText(TextBox textBox, string text)
{
for (int i = 0; i < 500; i++)
{
Invoke(new MethodInvoker(() =>
{
textBox.Text += text;
Thread.Sleep(2);
}));
}
}
(Jeśli jestem całkowicie błędne w tej sprawie nie mam nic z odczytaniem przez niektórych przykładach/wątków, ja wciąż staram się zobaczyć, co jest najlepszym sposobem, aby to zrobić, oprócz BackgroundWorker)
EDIT 2:
mam zmniejszyć liczbę wywołuje poprzez zmniejszenie ilości do pisania, ale aby zwiększyć opóźnienie daje ten sam efekt ciągłego pisania, tylko zmniejsza obciążenie.
private void writeText(TextBox textBox, string text)
{
for (int i = 0; i < 500; i++)
{
Invoke(new MethodInvoker(() =>
{
textBox.Text += text;
Thread.Sleep(2);
}));
}
}
Edycja 3:
przykład Sumeet za pomocą działa
Application.DoEvents();
(zauważyć s, .DoEvent nie działa, prawdopodobnie literówka: P), pisząc wiele strun jednocześnie & mający im pokazać postęp, a nie tylko wynik.
Więc Kod aktualizować ponownie :)
* Za pomocą nowego przycisku, aby utworzyć 5 wątków, które zapisują liczbę losową do obu pól tekstowych
private void writeText(TextBox textBox, string text)
{
for (int i = 0; i < 57; i++)
{
Invoke(new MethodInvoker(() =>
{
textBox.Text += text;
Thread.Sleep(5);
Application.DoEvents();
}));
}
}
private void btnNewThread_Click(object sender, EventArgs e)
{
Random random = new Random();
int[] randomNumber = new int[5];
for (int i = 0; i < 5; i++)
{
randomNumber[i] = random.Next(2, 9);
new Thread(() => writeText(txtOutput1, randomNumber[i-1].ToString())).Start();
new Thread(() => writeText(txtOutput2, randomNumber[i-1].ToString())).Start();
}
}
Rozważ użycie [ 'BackgroundWorker'] (http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx) jeśli masz długo działa zakonczeniu w tle, a interfejs musi pozostać elastyczny. –
@RobertHarvey To naprawdę nie pomogłoby w tym konkretnym przykładzie. – Servy
@Servy Ten konkretny przykład wydaje się ... uszkodzony. I wymyślone. Dla tego rodzaju rzeczy istnieje wytarta ścieżka. –