Wpf, mvvm, hur hantera loop som tar tid

Trädvy Permalänk
Medlem
Registrerad
Feb 2019

Wpf, mvvm, hur hantera loop som tar tid

Hej!

Har en Observable collection vars innehåll populerar en datagrid. Användaren kan sen markera en eller flera rader i griden och välja att exportera direkt till PDF. Programmet loopar genom alla valda rader och använder dess respektive id för att exportera rätt "items" via DevExpress Report.

Första problemet är att detta kan ta några minuter vilket gör att raderna måste förbli markerade tills det är klart. Det löste jag genom att alla SelectedItem.Id direkt läggs till i en ny List<int>.

Problem nummer två är att efter den åtgärden måste användaren fortfarande stanna kvar på den vyn tills exporten är klar. Just nu skickar jag därför listan med Id via eventaggregator till MainViewModel som sen skapar rapporterna.

Är detta ett ok sätt för är lösa den uppgiften eller hur bör man göra?

Tack på förhand.

Trädvy Permalänk
Medlem
Plats
127.0.0.1
Registrerad
Sep 2003

Datagridden (i View) är väll bindad till data i Viewmodel? (förmodligen din ObservableCollection)

Dvs så har du en datastruktur som du enkelt kan duplicera och skicka vidare (typ förnamn, efternamn, isSelected). Kanske skapa ett event (publish mha eventAggregator, eventArg är typen på din tabelldatastruktur) som en modul lyssnar på (subscribe), och när den tar emot eventet så extraherar den datan och kör sedan rapporteringen i en annan tråd.

1: Intel i7-3930K | 32GB Corsair Dominator GT | Asus Rampage IV Extreme x79 | 2 x 1080 GameRock Premium 8GB | 2 x Samsung Pro 840 512GB | Corsair AX1200i | BenQ XL2411 24" / W1070 135" | Bose QC25 | Windows 10 Pro x64 | HTC Vive |
2: Intel Core i7-4700HQ | 32GB RAM | Intel HM87 Express | GTX 780M | 17" | Windows 10 Pro x64 |

Trädvy Permalänk
Medlem
Registrerad
Feb 2019
Skrivet av Dalton Sleeper:

Datagridden (i View) är väll bindad till data i Viewmodel?

Dvs så borde du ha en datastruktur som du enkelt kan duplicera och skicka vidare (typ förnamn, efternamn, isSelected). Kanske skapa ett event (publish mha eventAggregator, eventArg är typen på din tabelldatastruktur) som en modul lyssnar på (subscribe), och när den tar emot eventet så extraherar den datan och kör sedan rapporteringen i en annan tråd.

Det stämmer, ObservableCollection finns på den DetailViewModel som är till den vyn.
Alltihop behöver jag inte skicka, rapportprogrammet hämtar datan direkt från SQL så allt som behövs är ett Id för varje rapport som ska skapas.
Det är ju lite så jag gör nu, skickar Id med eventAggregator som sen skapar rapporterna async.
Men det rätta är kanske att utföra arbetet med att skapa rapporterna i en ny tråd. Den avbryts inte om användaren lämnar vyn?

Skickades från m.sweclockers.com

Trädvy Permalänk
Medlem
Plats
127.0.0.1
Registrerad
Sep 2003

Ah, läste nog lite tokigt, förstod inte att du körde async, utan att du fick vänta på rapporten i viewn. Trådning och async bör ju hanteras i något som lever, en servicemodul eller main som du gör nu. Kör du async med callback till main ( utan await ) så bör det rulla på bra utan pauser på UI tråden. Callbacken kan invoka och ge meddelande eĺler progress till main om så behövs.

Jag förstod nog bara inte vad du hade löst och inte löst.

Skickades från m.sweclockers.com

1: Intel i7-3930K | 32GB Corsair Dominator GT | Asus Rampage IV Extreme x79 | 2 x 1080 GameRock Premium 8GB | 2 x Samsung Pro 840 512GB | Corsair AX1200i | BenQ XL2411 24" / W1070 135" | Bose QC25 | Windows 10 Pro x64 | HTC Vive |
2: Intel Core i7-4700HQ | 32GB RAM | Intel HM87 Express | GTX 780M | 17" | Windows 10 Pro x64 |

Trädvy Permalänk
Medlem
Registrerad
Feb 2019
Skrivet av Dalton Sleeper:

Ah, läste nog lite tokigt, förstod inte att du körde async, utan att du fick vänta på rapporten i viewn. Trådning och async bör ju hanteras i något som lever, en servicemodul eller main som du gör nu. Kör du async med callback till main ( utan await ) så bör det rulla på bra utan pauser på UI tråden. Callbacken kan invoka och ge meddelande eĺler progress till main om så behövs.

Jag förstod nog bara inte vad du hade löst och inte löst.

Skickades från m.sweclockers.com

Ursäkta att jag inte svarat förrän nu!
Nädå, det var jag som var otydlig. Jag missade skriva att jag körde async.
Ungefär så här ser det ut:

SomeDetailViewModel:

private void OnExportFileExecute() // ButtonCommand { _eventAggregator.GetEvent<PrintReportEvent>() .Publish( new PrintReportEventArgs { SomeItems = SomeItems, Type = "SomeType" }); }

MainViewModel:

private async void ReportAsync(PrintReportEventArgs args) { var items = (List<Data>)args.SomeItems; switch (args.Type) //Avgör om det är DirektPrint eller ExportToPDF { case "SomeType": await ExportFileAsync(items); break; } } private async Task ExportFileAsync(List<Data> items) { foreach (var item in items) { switch (item.SomeTypeId) //Avgör vilken Rapporttyp { case 1: await ExportSomeFileAsync(item.Id, item.FileName, item.FileNameRev); break; } } } private async Task ExportSomeFileAsync(string path, int id, string fileName, string fileNameRev) { string name = $"{path}\\Rapport {fileName} Rev {fileNameRev}.pdf"; var storage = new MemoryDocumentStorage(); var someReport= new SomeReport(); someReport.Parameters["Id"].Value = id; var cachedReportSource = new CachedReportSource(someReport, storage); await cachedReportSource.CreateDocumentAsync(); PdfExportOptions pdfOptions = someReport.ExportOptions.Pdf; pdfOptions.DocumentOptions.Producer = Environment.UserName.ToString(); pdfOptions.DocumentOptions.Subject = name; pdfOptions.DocumentOptions.Title = name; cachedReportSource.PrintingSystem.ExportToPdf(name, pdfOptions); }

Hoppas inte switcharna förvirrar för mycket.

Trädvy Permalänk
Medlem
Registrerad
Feb 2019

Så frågan kvarstår. Är detta ett ok sätt att göra det på eller helt mot praxis? Hur hade ni löst det?

Skickades från m.sweclockers.com

Trädvy Permalänk
Medlem
Plats
skåne
Registrerad
Jun 2004

Dom gånger jag kört många och tunga loopar har jag använt parallel.foreach för att få upp prestandan. Kollade inte så mycket på din kod men det kan kanske vara användbart här?

Skickades från m.sweclockers.com

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.

Trädvy Permalänk
Medlem
Registrerad
Feb 2019
Skrivet av kundun:

Dom gånger jag kört många och tunga loopar har jag använt parallel.foreach för att få upp prestandan. Kollade inte så mycket på din kod men det kan kanske vara användbart här?

Skickades från m.sweclockers.com

Väldigt intressant. Ska testa i helgen hur resultatet blir i mitt fall.
Tack för tipset!

Trädvy Permalänk
Medlem
Plats
skåne
Registrerad
Jun 2004

Just ja, glöm inte lock inne i loopen så du inte får kod som springer förbi varann 👍

Skickades från m.sweclockers.com

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.