Keresés
Hírlevél
 
Kiemelt témák
»10 éves a prog.hu
»Párhuzamos programozás
»Párhuzamos végrehajtás == szemléletváltás!
Állás/munka
»Tanárt keresek
»Port.hu film tartalmának kinyerése
»PHP programozó kerestetik
»Fejlesztői megbízásokat/munkát keresek
»Senior .Net fejlesztő szabad kapacitással
» több téma
Tudástár
?PHP:keresés szó szerint...
*PHP if-nél megakadtam
? torrent file helyett txt-t
Mobilinternet használata robotokban
?Delphi Form méretezési probléma
?HelpProvider alkalmazás .HLP fájlban
2 oldalas form
SetFocus hatástalan
?XP-n megy Win7-en megakad (Delphi)
?Hiányos mp3 hallgatás telefonról! C#
A legalsó scrollTop értéket nem veszi figyelembe
3 dív pozicionálása (2 egymás mellé, 1 ezek alá)
?Curl login Joomla-ba (PHP)
*Java Axis webservice file küldés és fogadás
?C# scrollozható form
» több téma
Társalgó
»Az általános műveltség része kellene, hogy legyen a programozni tudás?
»Get flood elleni védekezés
»Újra programozni fog a Facebook alapítója és multimilliárdos elnöke
»Firebird - Több adatbázis vagy egy?
»Clipper kontra XP
»Webshop ár kb...
»Hogy működik egy apróhirdető oldal (MySQL)?
»Körlevél script PHP + MySQL
»New project probléma VS 2010 C#
»Kezdőknek:grafikus felület választás
» több téma
ASPC#C++CSSDelphiFlashJavaJavaScriptPascalPerlPHPPythonuniPaaSVisual BasicVisual C++  »    

Tudástár

»

C# Dispatcher

»

C# Dispatcher

nyitotta: lastt, idő: 2012.01.09., moderátor: moderator
  Értesítés változás esetén Felvétel kedvencekhez Küldés emailben Nyomtatható verzió

Kategóriák:Programozási nyelvek » C#
Programozási platformok » .NET programozás

Kulcsszavak:
Sorrend:
Időzóna:
Blokkméret:
Oszd meg másokkal is!
Sziasztok!
A Dispatcher használatában kellene egy kis segítség. Először próbálkozom több-szálasítással. Ha jól olvastam utána, ezzel lehet egy thread-be és -ből adatot továbbítani.

Itt indítok egy új szálat(Pages.xaml.cs):
namespace InstallerPatch
{
        public partial class Pages : UserControl
        {
        public BackgroundWorker backgroundWorker = new BackgroundWorker();

                public Pages()
                {
                        this.InitializeComponent();

            this.backgroundWorker.DoWork += new DoWorkEventHandler(this.backgroundWorker_DoWork);
            this.backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.backgroundWorker_RunWorkerCompleted);
            this.backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(this.backgroundWorker_ProgressChanged);
            ProgressBarUpdate.PropertyChanged += new PropertyChangedEventHandler(progressValue_changed);

            this.backgroundWorker.WorkerSupportsCancellation = true;
            this.backgroundWorker.WorkerReportsProgress = true;
                }
...
Egy másik cs fájlban, és más névtérben van a "tömörítő", ami a háttérben fog futni. Ha statikusan adom meg neki az adatokat (input.file, output.file) persze megy, de dinamikusan, textbox-ból szeretném beolvastatni induláskor. Futás közben, vagy a befejezéskor már nem számít.
Illetve közben szeretném kiszedni is a folyamat állapotát, hogy hol tart, de gondolom a másik névtér miatt, a backgroundWorker.ReportProgress egyáltalán nem hívható meg a tömörítőből. Talán ez is megoldható Dispatcher-rel?
Vagy ha szerintetek van egyszerűbb megoldás is a fentebb leírtakra, mindenre nyitott vagyok.
WPF4-et használok.

Előre is köszi.
Szerintem a dispatcher inkább arra használatos, hogy a másik thread-ről tudd piszkálni a UI elemeket (pl a progressbart value-ját csak a dispatcher-en keresztül tudod változtatni.)
Egyébként szerintem csak simán add át a backroundworker objektuomt a csomagoló osztálynak és kész is. Vagy tárold el valahol, ahonnan eléri.
        BackgroundWorker worker;
        public MainWindow()
        {
            InitializeComponent();
            worker = new BackgroundWorker();
            worker.WorkerSupportsCancellation = true;
            worker.WorkerReportsProgress = true;

            worker.DoWork += new DoWorkEventHandler((object sender, DoWorkEventArgs e)=>
            {
                Wrapper wrapper = new Wrapper(worker, textbox1.Text, textbox2.Text);
                wrapper.DoIt();
            });
            worker.ProgressChanged += new
            ProgressChangedEventHandler((object sender, ProgressChangedEventArgs e)=>
            {
                // Show the progress
            });
        }

És a csomagoló osztályod:
    public class Wrapper
    {
        BackgroundWorker sender;
        public Wrapper(BackgroundWorker worker, string inputFilePath, string outputFilePath)
        {
            sender = worker;
        }

        public void DoIt()
        {
            sender.ReportProgress(...);
        }
    }

Ja és a worker-t akkor indítsd el, amikor megvannak az adatok a textboxokból. előzmény
Az elérést végül sikerült úgy megcsinálnom, hogy egy névtérbe raktam mindent, nem sok fájlban kellett módosítani.

De bármit próbálok neki bemenetre adni, olyan hibát dob, hogy az másik thread. előzmény
Nem szükséges mindent egy névtérbe rakni, sőt! Ha egy névteret használni szeretnél, használd a "using" kulcsszót!

Hogy világos legyen a koncepció: fut a GUI-szál, az jeleníti meg a control-okat, az tartalmazza a TextBox-ot, a ProgressBar-t stb. Ha a tömörítést a GUI-szálban indítanád el, a program lemerevedne, mivel amíg dolgozik, addig nem frissíti a GUI-t.

Ezért célszerű használni a BackgroundWorker-t, ami egy második szálat indít a programodban. Így amíg a második szálon fut a tömörítés, a GUI is aktív marad (plusz le lehet kezelni, ha a user Cancel-t nyom stb.).

Egy probléma jelentkezik azonban, hogy az egyik szálról egy másik szál metódusait, property-jeit hívni nem lehet közvetlenül. Erre való az Invoke() ill. BeginInvoke(), de azzal meglehetősen bonyolultan lehet egy egyébként gyakori problémát kezelni.

Ezért fejlesztették ki a Dispatcher-t, amely használatával egyszerűen tudod a BackgroundWorker-ből (azaz a másik száladból) a GUI-száladat frissíteni.

A te első problémád megoldásához (átadni a TextBox property-t a GUI-szálról a BackgroundWorker-nek) egyáltalán nem szükséges Dispatcher. Ahhoz, hogy a BackgroundWorker frissítse a GUI-t, na ahhoz szükséges a Dispatcher.

Nézd meg Laszlo_Kiss megoldását, próbáld azt működésre bírni, akkor láthatod, hogy hogyan kéne használni, utána kérdezz, ha valami nem világos. előzmény
Már régen használtam ezt, így gyorsan létrehoztam, hogy felidézzem a részleteket, és nocsak! Dispatcher ehhez a feladathoz egyáltalán nem szükséges, mivel a BackgroundWorker tud hívni (raise) egy ReportProgress eseményt, amivel így szépen át lehet adni a paramétereket a GUI-szálnak.

Szóval itt egy kis minta-program, egy darab WPF ablakkal:

MainWindow.xaml

<Window x:Class="WPFApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="4*"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="5*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Button Content="Start" Grid.Row="0" Grid.Column="0" Width="75" Height="23" HorizontalAlignment="Center" Name="btnStart" VerticalAlignment="Center" Click="btnStart_Click" />
        <ProgressBar Name="pbarUpdate" Grid.Row="0" Grid.Column="1" Height="25" Margin="5"></ProgressBar>
    </Grid>
</Window>


MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace WPFApp
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private BackgroundWorker backgroundWorker;

        public MainWindow()
        {
            InitializeComponent();
            InitBackgroundWorker();
        }

        private void InitBackgroundWorker()
        {
            backgroundWorker = new BackgroundWorker();

            backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
            backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);

            backgroundWorker.WorkerSupportsCancellation = true;
            backgroundWorker.WorkerReportsProgress = true;
        }

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            // a files tömb-be lehet lekérdezni a file-neveket a TextBox-okból
            string[] files = { "inputfile.txt", "outputfile.txt" };

            btnStart.IsEnabled = false;
            // átadjuk a paramétereket
            backgroundWorker.RunWorkerAsync(files);
        }

        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            // ez a worker-szál, itt vannak a paraméterek
            string[] files = (string[])e.Argument;

            for (int i = 0; i <= 100; i += 10)
            {
                backgroundWorker.ReportProgress(i);
                System.Threading.Thread.Sleep(500);
            }
        }

        private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            // ez GUI-szál, nem kell Dispatcher
            pbarUpdate.Value = e.ProgressPercentage;
        }

        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // ez GUI-szál ismét, természetesen
            btnStart.IsEnabled = true;
            pbarUpdate.Value = 0;
        }
    }
}
előzmény
Misit margaritas ante porcos. előzmény
Ha ezzel az inaktivitásomra céloztál volna, az sajnos így van, de nincs elfelejtve a dolog, csak elég sok dolgom van mostanában, meg kicsit újradolgoztam a GUI-t, de mindent kipróbálok, amint tudom. előzmény
Oszd meg másokkal is!
Belépés
E-mail cím:
Jelszó:

cvonline.hu
»iOS fejlesztő
»Senior web programozó
»Java fejlesztő (Bécs)
»Java fejlesztő (front-end, backend)
»PHP fejlesztő (Ausztria, Németország)
»Solaris rendszermérnök
» még több állás
Kérdésed van?
Problémád, kérdésed van? Segítünk neked is. Csak kattints ide!
RSS források
-Hírek
-Cikkek
-Fórumok
-Állás/munka
Top pontgyűjtők
»Árnyék1.100
»silentworks910
»Robi80910
»szabofe860
»bubori.attila760
»djjjozsi680
»Galovics660
»Riha590
»Frostech0560
»Csaboka2550
A nap kifejezései
»Adatszegmens
»Konstans
»Makró
» ugrás a wikire
Hírek
»Az általános műveltség része kellene, hogy legyen a programozni tudás?
»Újra programozni fog a Facebook alapítója és multimilliárdos elnöke
»Vizuális felülettervezőt adott ki .NET-es Android-alkalmazásfejlesztéshez a Xamarin
» több hír
PC Fórum hírek
»Elvennék és felhasználóinak adnák a Facebook összes pénzét
»Rejtélyes ikont dugdosgat a Microsoft a Windows 8-ban
»Út a Windows 8-ig - a Windows rendszerek három évtizedének története, képekben
»Mától bárki regisztrálhat a so.cl-ra, a Microsoft közösségi oldalára
»Megérkeztek az első képek az Unreal Engine 4 játékmotorról
»Itt az első videó a a Firefox Windows 8-as változatáról
»Nyártól akár 150 megabites nethozzáférést is ad az Invitel
»Kilenc kritikus biztonsági hibát javít az új Google Chrome
Top wikieditorok
»Sting
»Doi
»FlamingClaw
»Argathron
»Csaboka2
»Muki987
»NevemTeve
»Ivn
»Kelemzol
»Joexy
» ugrás a wikire