Cześć, podjąłem się amatorskiego wykonania aplikacji do wypełniania protokołów, które trafiają do Word'a. Chciałem aby program na bieżąco przeładowywał zawartość utworzonego dokumentu tzn. pobierał tekst z TextBox'ów i wpisywał go w odpowiednie miejsca. Czy jest to w ogóle możliwe? Próbowałem poprzez stworzenie dodatkowego okienka, w którym w nieskończonej pętli byłyby podmieniane zawartości stringów ale po kompilacji nawet nie pojawia się okienko główne tylko od razu działa pętla w tym drugim.

- Rejestracja:ponad 4 lata
- Ostatnio:18 dni
- Postów:9
Jak nieskończona pętla to raczej przyda ci się oddzielny wątek do tego, czy tam Taski chyba są w c#. Nowe okienko ci nic nie da


- Rejestracja:ponad 6 lat
- Ostatnio:5 dni
- Postów:182
jak chcesz, aby mozna bylo jednoczesnie korzystać z aplikacji no musisz to zrobić w innym wątku i tyle ;)
w uproszczeniu
new System.Threading.Tasks.Task(() =>
{
while (twój_warunek)
{
ZapiszKontrolkeDoWorda();
System.Threading.Thread.Sleep(1000); // milisekund
}
}).Start();
tylko tam sobie musisz doczytać o cancellationToken, itd - tj. musisz przy zamykaniu aplikacji (albo w jakimś innym wybranym przez ciebie momencie) ubić tego taskulca ;)
- Rejestracja:około 22 lata
- Ostatnio:około miesiąc
- Postów:5042
Są jeszcze inne opcje. Np. BackgroundWorker. Czy tam BackgroundTask. Można też zrobić asynchronicznego cyklicznego Taska. Kod będzie podobny do tego pokazanego przez @heyyou tyle że zamiast Thread.Sleep, daj Task.Delay. I użyj async/await w tym miejscu:
new Task(async () =>
{
while(...)
{
DoJob();
await Task.Delay(1000);
}
}
Oczywiście, jeśli DoJob robi coś na kontrolkach, to musisz to odpowiednio synchronizować, bo nie możesz odwołać się do kontrolki z innego wątku niż główny.
- Rejestracja:ponad 4 lata
- Ostatnio:około 2 lata
- Postów:27
@shuz: jeżeli zrobisz to aktywną pętlą w osobnym wątku, to program będzie generował dokument nawet jeżeli nie ma żadnych zmian. To będzie upierdliwe jak ktoś będzie chciał otworzyć dokument, zmienić nazwę albo przenieść.
Możesz pokusić się o coś bardziej zwinnego np.:
Gdy textbox rzuca TextChanged, wtedy uruchamiasz 3 sekundowy licznik.
a) jeżeli pojawiło się nowe zdarzenie TextChanged (globalnie dla wszystkich TextBoxów, które powodują nadpisanie dokumentu) restartujesz licznik
b) jeżeli minęły 3 sekundy, ustawiasz wspólną flagę na true
.
Pozwala to uniknąć przegenerowania pliku, jeżeli ktoś wciąż coś pisze.
W wątku obok cały czas monitorujesz flagę w pętli i jeżeli jest ona ustawiona na true
to zmieniasz ją na false
i generujesz dokument. Jeżeli flaga jest ustawiona na false
robisz jakieś sleep na sekundę.
Aby robić to jeszcze bardziej zwinne możesz poczytać o wybudzaniu wątku gdy następuje zdarzenie, wtedy w ogóle pozbywasz się aktywnego czekania.
- Rejestracja:około 4 lata
- Ostatnio:4 dni
- Postów:506
Może trochę przerost formy nad treścią, pisane na szybko ale u mnie sprawdzało się coś na wzór tego (kolega wyżej to ładnie opisał)
public class PdfGenerator<Args, Return>
{
public delegate Return GeneratePdfDelegate(Args args);
public PdfGenerator(TimeSpan delay, GeneratePdfDelegate generatePdfMethod)
{
Delay = delay;
this.generatePdfMethod = generatePdfMethod;
timer = new Timer();
timer.AutoReset = false;
timer.Interval = Delay.TotalMilliseconds;
timer.Elapsed += Timer_Elapsed;
}
public TimeSpan Delay { get; private set; }
private GeneratePdfDelegate generatePdfMethod;
private Timer timer;
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
RequestgeneratePdf?.Invoke(this, EventArgs.Empty);
}
public event EventHandler<EventArgs> RequestgeneratePdf;
public event EventHandler<Return> PdfGenerated;
public void TextChange()
{
timer.Stop();
timer.Start();
}
public async void GeneratePdf(Args args)
{
await Task.Run(() =>
{
Return myPdf = generatePdfMethod(args);
PdfGenerated?.Invoke(this, myPdf);
});
}
}
I przykład użycia bardzo prosty:
public class Main
{
public Main()
{
pdfGenerator = new PdfGenerator<string, string>(new TimeSpan(0, 0, 3), (string args) => {
return $"My Pdf with text {args}";
});
pdfGenerator.RequestgeneratePdf += PdfGenerator_RequestgeneratePdf;
pdfGenerator.PdfGenerated += PdfGenerator_PdfGenerated;
}
PdfGenerator<string, string> pdfGenerator;
private void TextChange(object sender, EventArgs eventArgs)
{
pdfGenerator.TextChange();
}
private void PdfGenerator_RequestgeneratePdf(object sender, EventArgs e)
{
pdfGenerator.GeneratePdf(MyTextBox.text);
}
private void PdfGenerator_PdfGenerated(object sender, string e)
{
string MyPdf = e;
}
}
Pdf będzie się generował po upłynięciu delay
czasu bezczynności.
- Rejestracja:ponad 5 lat
- Ostatnio:7 dni
- Postów:20
Jeżeli nie musisz targetowac innych platform niż Windows, to DispatcherTimer jest prosty i miły w użyciu oraz idealnie pasuje do wymagań.