Laden...

Forenbeiträge von CSharpFreak Ingesamt 42 Beiträge

07.02.2017 - 11:40 Uhr

Dieser "infinity" Task würde ja im Model/Service laufen. Das ViewModel hängt sich dann als Subscriber da rein und verändert die Eigenschaft synchronisiert im passenden Thread Kontext.

Nur so hat man auch die Chance dort noch regulatorisch einzugreifen (wenn z.B. zu viele Änderungen pro Sekunde dort reinlaufen, dann übernimmt man nicht jeden Wert in die Anzeige, sondern nur maximal 10 Änderungen pro Sekunde).

Der Task läuft im Model, das ist richtig.
Wie ist das mit dem Subscriber gemeint?

07.02.2017 - 10:47 Uhr

Erst einmal vielen Dank für das ganze Feedback 😃

Der oben angegebene Code-Schnipsel war für das jeweilige ViewModel vorgesehen.

Dieses Model sieht dann nicht vor, dass eine 'infinity' Task Properties verändern kann/sollte?

06.02.2017 - 23:10 Uhr

Gute Abend 😃,

ich würde gerne eure Meinung zu diesen zwei Varianten hören, welche das DataBinding ThreadSafe machen sollen.
Oder ist das eine völlig falsche Herangehensweise an diesem Problem?

Variante 1:

        public event PropertyChangedEventHandler PropertyChanged;
		
        public virtual void OnPropertyChanged([CallerMemberName] String propertyName = null)
        {
            PropertyChangedEventHandler eventHandler = PropertyChanged;
            if (eventHandler != null)
            {
                Delegate[] delegates = eventHandler.GetInvocationList();
                foreach (PropertyChangedEventHandler handler in delegates)
                {
                    DispatcherObject DispatcherObject = handler.Target as DispatcherObject;

                    if (DispatcherObject != null && DispatcherObject.CheckAccess() == false)
                    {
                        DispatcherObject.Dispatcher.Invoke(DispatcherPriority.DataBind, handler, this, new PropertyChangedEventArgs(propertyName));
                    }
                    else
                    {
                        handler(this, new PropertyChangedEventArgs(propertyName));
                    }
                }
            }
        }

Variante 2:

        public Dispatcher DispatcherObject { get; set; } = Dispatcher.CurrentDispatcher;
        
        public event PropertyChangedEventHandler PropertyChanged;
		
        public virtual void OnPropertyChanged([CallerMemberName] String propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
          
            if (handler != null && DispatcherObject != null)
            {
                if (DispatcherObject.CheckAccess())
                {
					handler(this, new PropertyChangedEventArgs(propertyName));
                }
                else
                {
                   DispatcherObject.Invoke(() => handler(this, new PropertyChangedEventArgs(propertyName)));
                }
            }
        }

Grüße

08.05.2016 - 23:33 Uhr

Hallo -

ich beschäftige mich momentan ein wenig mit JSON und wollte es als "Datenbank" nutzen.
Das Problem welches ich habe ist, dass wenn die Datenbank riesig wird, das schreiben auf die Platte mehr oder weniger Zeit in Anspruch nimmt.

Gibt es hierfür bereits eine Lösung? Das evtl. nur die Änderungen geschrieben werden? Oder hätte jemand einen Ansatz für mich, wie man dieses Problem "elegant" lösen kann?

viele Grüße

07.03.2016 - 13:32 Uhr

Vielen Dank erst einmal für die zahlreichen Antworten!

Ich möchte keine Schadsoftware basteln... Es geht mir lediglich darum eine bereits vorhandene Assembly zu erweitern ohne sie nachbauen zu müssen.

An dem tauschen des IL-Codes hab ich auch schon gedacht, dass ist ja generell immer möglich... Ich dachte jedoch das es dafür eine bessere Möglichkeit gibt. Ich denke mal, dass ich einen kompletten Rework der Klasse machen werden.

06.03.2016 - 23:20 Uhr

Hallo -

ich habe ein Problem und zwar möchte ich gerne eine Methode die wie folgt deklariert ist überschreiben:


internal virtual void DoSome(Object X)
{
}

Sie befindet sich allerdings in einer eigenen Assembly. Ist das überschreiben mit Hilfe von Reflektion möglich?
Mir geht es darum, dass ich an den Parameter 'X' heran komme, um ihn anschließend modifizieren zu können.

MfG

06.01.2016 - 04:26 Uhr

Hallo -
ich habe eine Frage bezüglich des speichern der default Properties eines VS-Projekts.
Gibt es die Möglichkeit den Speicherort zu ändern, sodass diese nicht im '....AppData\Local[Anwedungsname]' abgespeichert werden?
Oder muss ich einen eigenen Wrapper für die Properties schreiben?
Ich finde leider nur Sachen die sich auf das .Net 2.0 beziehen, wo gesagt wird das man den Speicherort nicht abändern kann.
Hat sich daran bisher nichts geändert?

MfG

22.12.2015 - 23:24 Uhr

Die Frage ist: was soll das bringen?
Warum soll die Liste asynchron sein? Aktionen sollen doch asynchron sein...

Sieht für mich nach nem Konzeptionsfehler aus.

Die Entscheidung, ob ein Object aus der Liste gelöscht wird, hängt von einer Datenbankabfrage (asyncron) ab. Und damit die GUI nicht einfriert wollte ich das so gestallten.

Das kann man sicher noch irgendwie eleganter lösen... jedoch dachte ich für mich, dass ich eine gefunden hätte...
Ich werde die Vorgehensweise noch einmal überdenken.

Unabhängig von Sinn oder Unsinn (persönlich halte ich es für Unsinn) müsste die Erweiterung so aussehen:

  
    public static class Extension  
    {  
        public async static Task<int> RemoveAsync<T>( this ICollection<T> collection, Func<T, bool> condition )  
        {  
            return await Task.Run( () =>  
            {  
                var items = collection.Where( condition ).ToList();  
                foreach ( var item in items )  
                {  
                    collection.Remove( item );  
                }  
                return items.Count;  
            } );  
        }  
    }  
  

und der Aufruf

  
        private async void button_Click(object sender, RoutedEventArgs e)  
        {  
            var count = await DataCollection.RemoveAsync( o => o.Name.Length > 3 );  
            // noch was mit count machen?  
        }  
  

Das Funktioniert an sich aber lässt keine asyncronen Methoden in der Convention zu...

22.12.2015 - 21:30 Uhr

Ja - das habe ich mir so anfangs auch gedacht aber dann...


List<T> itemsToRemove = OCollection.Where(await Condition).ToList();

Besitzt keine Methode mit Func<T, Task<Boolean>> als Parameter, daher dachte ich, dass ich es irgendwie anpassen kann, indem ich eine Task übergebe.

22.12.2015 - 21:05 Uhr

Hallo -

ich habe ein (Verständnis?)-Problem. Und zwar bezieht es sich auf die ObservableCollection.
Ich wollte diese um ein Paar Async-Funktionen erweitern.

z.B. RemoveAsync


        public static Task<Int32> RemoveAsync<T>(this ObservableCollection<T> OCollection, Task<Func<T, Boolean>> Condition)
        {
            return Task.Run<Int32>(async () =>
            {
                List<T> itemsToRemove = OCollection.Where(await Condition).ToList();

                foreach (T itemToRemove in itemsToRemove)
                {
                    OCollection.Remove(itemToRemove);
                }

                return itemsToRemove.Count;
            });
        }


    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        public class ObjectItem
        {
            public String Name;
        }

        public ObservableCollection<ObjectItem> DataCollection { get; set; } = new ObservableCollection<ObjectItem>()
        {
            new ObjectItem() { Name = "A" },
            new ObjectItem() { Name = "AB" },
            new ObjectItem() { Name = "ABC" },
            new ObjectItem() { Name = "ABCD" },
            new ObjectItem() { Name = "ABCDE" },
            new ObjectItem() { Name = "ABCDEF" },
        };

        private void button_Click(object sender, RoutedEventArgs e)
        {
            DataCollection.RemoveAsync<ObjectItem>(async (Obj) => 
            {
                await Task.Delay(1000);
                return Obj.Name.Length > 3;
            });
        }
    }

Als Fehlermeldung bekomme ich nun:> Fehlermeldung:

Fehler CS1660 "Lambda-Ausdruck" kann nicht in den Typ "Task<Func<MainWindow.ObjectItem, bool>>" konvertiert werden, da es kein Delegattyp ist.

Was mache ich falsch? Ich würde das ganze gerne so auslegen, dass ich in der "Condition" auch await nutzen kann.

14.12.2015 - 15:29 Uhr

Btw, Button_Click weist schon darauf hin, dass du MVVM nicht wirklich verinnerlicht hast, genau wie das Setzen des DataContext im Code-Behind. Man sollte schon wirklich, wirklich gut begründen, wenn man bei MVVM Code-Behind nutzt (die Faelle gibt es, sind aber wirklich selten).

Das verstehe ich nicht... wie wäre es denn richtig?

Was auch wichtig: Es ist glaub BrainF...k, von ObservableCollection<T> zu erben. Ich sagte glaub in meim 1.Post: Die ItemSource der DGs sollte an eine Property vom Typ ObservableCollection<T> binden.

Ich fand es für mich sinnig davon zu erben, da es mir einfach nur einen Member ersparen sollte bzw. es am ende eine "Liste" sein soll mit Membern, in der vorgefertigte filter sind.

Ich habe eine weitere tolle Sache entdeckt "ObservableCollectionView", diese sollte mir die Collection filtern, wenn ich das richtig verstanden habe. Ich bin wie im Beispiel vorgegangen jedoch werden immer noch weiterhin nur die Properties geändert.


    public class ObjectItem : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void SetProperty<T>(ref T field, T value, [CallerMemberName] String name = "")
        {
            if (!EqualityComparer<T>.Default.Equals(field, value))
            {
                field = value;
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(name));
                }
            }
        }

        private String _Name;
        public String Name
        {
            get { return _Name; }
            set { SetProperty(ref _Name, value); }
        }
    }

    public class BindingTest : MtObservableCollection<ObjectItem>
    {
        public ObservableCollectionView<ObjectItem> OBJLessTree { get; set; }
        public ObservableCollectionView<ObjectItem> OBJGreaterTree { get; set; }
        public BindingTest()
        {
            OBJLessTree = new ObservableCollectionView<ObjectItem>(this);
            OBJGreaterTree = new ObservableCollectionView<ObjectItem>(this);

            OBJLessTree.Filter = p => p.Name.Length < 3;
            OBJGreaterTree.Filter = p => p.Name.Length > 3;

            this.Add(new ObjectItem() { Name = "A"});
            this.Add(new ObjectItem() { Name = "B" });
            this.Add(new ObjectItem() { Name = "C" });
            this.Add(new ObjectItem() { Name = "FIRST" });
            this.Add(new ObjectItem() { Name = "SECOND" });
            this.Add(new ObjectItem() { Name = "THIRD" });
        }
    }

<Window x:Class="ExampleBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ExampleBinding"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="525">
    <Grid>
        <DataGrid x:Name="LessDataGrid" 
                  ItemsSource="{Binding OBJLessTree, UpdateSourceTrigger=PropertyChanged}"
                  AutoGenerateColumns="False"
                  IsReadOnly="True" VerticalAlignment="Top" Height="126" Margin="10,10,300,0">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Path=Name}"/>
            </DataGrid.Columns>
        </DataGrid>
        <DataGrid x:Name="GreaterDataGrid" 
        	ItemsSource="{Binding OBJGreaterTree, UpdateSourceTrigger=PropertyChanged}"
        	AutoGenerateColumns="False"
            IsReadOnly="True" VerticalAlignment="Top" Height="126" Margin="300,10,10,0">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Path=Name}"/>
            </DataGrid.Columns>
        </DataGrid>
        <Button x:Name="button" Content="Change!!!" Margin="10,147,10,0" VerticalAlignment="Top" Height="65" Click="button_Click"/>
    </Grid>
</Window>

    public partial class MainWindow : Window
    {
        public BindingTest ABC { get; set; } = new BindingTest();
        public MainWindow()
        {
            InitializeComponent();
            DataContext = ABC;
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            ABC.First().Name = "ABCDEFGH";
        }
    }

Ich benutze gerne
>
, damit ich nicht manuell INotifyPropertyChanged implementieren muss.

Dann wird für jedes Public Property mit getter und setter INotifyPropertyChanged direkt beim Compilieren generiert.

Werde ich später noch ausprobieren, da ich vorerst das Vorgehen verstehen möchte.
Danke für den Hinweis für das NuGet.

14.12.2015 - 04:22 Uhr

Vielen Dank erst noch einmal für eure Hilfe. Ich habe mir das MVVM-Pattern nochmal angeschaut und nun auch hoffentlich etwas verinnerlicht.
Und dabei noch etwas interessantes entdeckt, dass seit dem .Net 4.5 eine Vereinfachung bezüglich des PropertyChanged existiert =)

Ich habe das Beispiel daraufhin etwas abgeändert. Allerdings stehe ich nun vor dem Problem mit dem CollectionChanged Event. Das Event sollte ja von der ObservableCollection implementiert werden.


    public class ObjectItem : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void SetProperty<T>(ref T field, T value, [CallerMemberName] String name = "")
        {
            if (!EqualityComparer<T>.Default.Equals(field, value))
            {
                field = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(name));
                }
            }
        }

        private String _Name;
        public String Name
        {
            get { return _Name; }
            set { SetProperty(ref _Name, value); }
        }
    }

    public class BindingTest : ObservableCollection<ObjectItem>
    {
        public IEnumerable<ObjectItem> OBJLessTree { get { return this.Where(CItem => CItem.Name.Length < 3); } }
        public IEnumerable<ObjectItem> OBJGreaterTree { get { return this.Where(CItem => CItem.Name.Length > 3); } }
        public BindingTest()
        {
            Add(new ObjectItem() { Name = "A"});
            Add(new ObjectItem() { Name = "B" });
            Add(new ObjectItem() { Name = "C" });
            Add(new ObjectItem() { Name = "FIRST" });
            Add(new ObjectItem() { Name = "SECOND" });
            Add(new ObjectItem() { Name = "THIRD" });
        }
    }

<Window x:Class="ExampleBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ExampleBinding"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="525">
    <Grid>
        <DataGrid x:Name="LessDataGrid" 
                  ItemsSource="{Binding OBJLessTree}"
                  AutoGenerateColumns="False"
                  IsReadOnly="True" VerticalAlignment="Top" Height="126" Margin="10,10,300,0">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Name}"/>
            </DataGrid.Columns>
        </DataGrid>
        <DataGrid x:Name="GreaterDataGrid" 
        	ItemsSource="{Binding OBJGreaterTree}"
        	AutoGenerateColumns="False"
            IsReadOnly="True" VerticalAlignment="Top" Height="126" Margin="300,10,10,0">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Name}"/>
            </DataGrid.Columns>
        </DataGrid>
        <Button x:Name="button" Content="Change!!!" Margin="10,147,10,0" VerticalAlignment="Top" Height="65" Click="button_Click"/>
    </Grid>
</Window>

    public partial class MainWindow : Window
    {
        public BindingTest ABC { get; set; } = new BindingTest();
        public MainWindow()
        {
            InitializeComponent();
            LessDataGrid.DataContext = ABC;
            GreaterDataGrid.DataContext = ABC;
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            ABC.First().Name = "ABCDEFGH";
        }
    }

13.12.2015 - 17:53 Uhr

Vielen Dank! Ihr habt beide recht, ich habe das View nicht richtig gesetzt :S
Und soweit ich gelesen habe muss man nicht zwanghaft manuell die "INotifyPropertyChanged" implementieren da dies automatisch geschieht, wenn man {get; set; } deklariert?
Die List<> habe ich in ObservableCollection<> geändert.

Allerdings stelle ich mit noch die Frage wie das mit IEnumerable ist, wie kann ich ein Solches Attribut binden, sodass es sich immer aktualisiert?

12.12.2015 - 23:08 Uhr

Hallo -
ich habe ein Problem mit dem Binding. Und zwar möchte ich das Property OBJ an dem DataGrid binden. Nur leider funktioniert es so nicht.

Klassen:


    public class ObjectItem
    {
        public String Name { get; set; }
    }

    public class BindingTest : List<ObjectItem>
    {
        public IEnumerable<ObjectItem> OBJ { get { return this.Where(CItem => CItem.Name.Length < 5); } }
        public BindingTest()
        {
            Add(new ObjectItem() { Name = "A" });
            Add(new ObjectItem() { Name = "B" });
            Add(new ObjectItem() { Name = "C" });
            Add(new ObjectItem() { Name = "DONTLIST" });
        }
    }

    public class MainObject
    {
        public BindingTest BIN { get; set; } = new BindingTest();
    }

XAML:

<Window x:Class="ExampleBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ExampleBinding"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid Loaded="Grid_Loaded">
        <DataGrid x:Name="WORKS" 
                  ItemsSource="{Binding ABC2.OBJ}"
                  AutoGenerateColumns="False"
                  HorizontalAlignment="Left" VerticalAlignment="Top" Height="126" Width="163" Margin="10,79,0,0">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Name}"/>
            </DataGrid.Columns>
        </DataGrid>
        <DataGrid x:Name="DONTWORK" 
        	ItemsSource="{Binding ABC.BIN.OBJ}"
        	AutoGenerateColumns="False"
        	HorizontalAlignment="Left" VerticalAlignment="Top" Height="126" Width="163" Margin="340,79,0,0" DataContext="">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Name}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

    public partial class MainWindow : Window
    {
        public MainObject ABC { get; set; } = new MainObject();
        public BindingTest ABC2 { get; set; } = new BindingTest();
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        private void Grid_Loaded(object sender, RoutedEventArgs e)
        {

        }
    }

Mit freundlichen Grüßen

19.01.2015 - 15:05 Uhr

Danke - die Abbildung habe ich schon gesehen, sie ist sehr schön dargestellt und leicht verständlich auch, wenn sie nicht zu 100% korrekt ist wie du sagst.

Okay also bleibt mir der wechsel nicht aus, wenn ich mit async/await arbeite.
Um das ganze noch zu vervollständigen - Nach dem await im ersten Beispiel würde sich der nachfolgende Code aber nicht im UI-Thread befinden?

19.01.2015 - 13:25 Uhr

Okay aber dann heißt doch genau mein erstes Beispiel das er wieder in den selben Context kommen soll, wenn er den Request fertig abgesetzt hat... das ConfigureAwait(true) redundanz ist weiß ich daher habe ich ja geschrieben, dass ich es nochmal explizit angegeben habe.

Aber genau das ist ja mein Problem das ich beim Ersten Beispiel das Resultat nicht nachvollziehen kann. Soweit ich verstanden habe gibt mir Task.CurrentId eine eindeutige Nummer der momentanen Task zurück und im ersten Beispiel ergibt der zweite Aufruf keine Task-ID, da es evtl. keine Task ist sondern der UI-Thread?

19.01.2015 - 12:24 Uhr

In erster Linie geht es mir dort momentan um's Verständnis.
Mit 'nichts' meine ich das die Methode .toString einen leeren String zurück gibt hätte ich vllt. anders schreiben sollen.

Zudem geht es mir um die Performance. Wenn ich einen Context wechsel vornehme, wie es im ersten beispiel der Fall ist?, leidet doch am ende diese darunter?

Das beispiel bildet ja quasi eine Task ab, in der ein sequenzieller Ablauf stattfindet/stattfinden soll.

Wegen dem 'ConfigureAwait(true)' - Wollte ich explizit noch einmal sagen das er keinen Context-Wechel machen darf/soll.

18.01.2015 - 23:58 Uhr

Hallo - ich spiele momentan ein wenig mit den Tasks nur verstehe ich da eine Sache nicht.

                Task.Factory.StartNew<Task>(async () =>
                {
                    HttpClient WebCaller = new HttpClient();
                    MessageBox.Show(Task.CurrentId.ToString()); // Task-ID => 1

                    await WebCaller.GetAsync("http://www.google.de").ConfigureAwait(true);

                    MessageBox.Show(Task.CurrentId.ToString()); // Task-ID => NICHTS
                }, new CancellationToken(), TaskCreationOptions.LongRunning, TaskScheduler.Default);

Und zwar anhand dieses Beispiels - Ich lasse mir zwei mal die Task-ID ausgeben einmal vor dem await und danach. Davor wird mir wie erwartet Task-ID 1 ausgegeben beim Zweiten mal jedoch nichts - Bin ich nach diesem Aufruf im UI-Thread gelandet?
Hätte ich nicht normal in der selben Task bleiben müssen da 'ConfigureAwait(true)' gesetzt ist?

Im zweiten Beispiel bleibe ich wie gewollt in der selben Task mit der ID 1.

                Task.Factory.StartNew<Task>(async () =>
                {
                    HttpClient WebCaller = new HttpClient();
                    MessageBox.Show(Task.CurrentId.ToString());

                    Task<HttpResponseMessage> WarteTest = WebCaller.GetAsync("http://www.google.de");
                    WarteTest.Wait();

                    MessageBox.Show(Task.CurrentId.ToString());
                }, new CancellationToken(), TaskCreationOptions.LongRunning, TaskScheduler.Default);
08.12.2014 - 23:45 Uhr

Scheint so als hätte keiner einer Idee? 😦

25.11.2014 - 01:55 Uhr

Moin -

ich habe eine Frage bezüglich der statischen Klasse "ServicePointManager".
Ich weiß, dass die Verbindungen durch die jeweilige URI Identifiziert werden. [ServicePointManager-Klasse]

Mein Problem ist nun das ich die selbe URL über verschiedene Interfaces rausschicken möchte ohne dabei die Verbindung schließen zu müssen.

BSP:

            String URLForRequest = @"https://www.google.de";
            ServicePointManager.FindServicePoint(new Uri(URLForRequest)).BindIPEndPointDelegate = delegate(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount)
            {
                return new IPEndPoint(IPAddress.Parse("IP_1"), 0);
            };

            //Request1 https://www.google.de

            ServicePointManager.FindServicePoint(new Uri(URLForRequest)).BindIPEndPointDelegate = delegate(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount)
            {
                return new IPEndPoint(IPAddress.Parse("IP_2"), 0);
            };

            //Request2 https://www.google.de

Problem hierbei ist das es sich um eine statische Klasse handelt und "FindServicePoint" natürlich den selben ServicePoint für beide Requests liefert und ich somit die Delegate überschreibe...

Meine Frage ist nun ob es überhaupt möglich ist oder ob ich jeweils eine Anwendung für das jeweilige Netzwerk haben muss.

MfG

18.11.2014 - 14:51 Uhr

Vielen Dank für den Hinweis - Ich habe mir jetzt mal genauer angeschaut... hätte ich lieber mal anfangs direkt geschaut hätte ich mir viel arbeit ersparen können, Danke.

17.11.2014 - 22:47 Uhr

Danke für eure Hilfe - Ich habe es nun mit Hilfe des SerivePointManager's erfolgreich lösen können.

Mir ist jedoch eine Sache aufgefallen, wenn man "WebRequest" mit "HttpClient" vergleicht ist die "WebRequest" um einiges schneller... wie kommt es zu diesem Effekt?

Habe mich beim Test auf diesen Thread bezogen (Antwort von Abt).

MfG

16.11.2014 - 17:09 Uhr

Als Beispiel:

HttpClient MyClient = new HttpClient(new WebRequestHandler
						{
							AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
							UseCookies = true,
							CookieContainer = new CookieContainer(),
							Proxy = new WebProxy()
							{
								Address = new Uri("http://X.X.X.X:X"),
								Credentials = new NetworkCredential("USER", "PW"),
							} ,
							UseProxy = true,
							UnsafeAuthenticatedConnectionSharing = true
						});
HttpResponseMessage MyMessage_1 = await MyClient.GetAsync("https://www.google.de");
HttpResponseMessage MyMessage_2 = await MyClient.GetAsync("https://www.yahoo.de");

Da passiert es halt manchmal das Host nicht reagiert,
Bzw. wieso werden hierbei 2 Sockets geöffnet und das alte (vom google request) "reused"?
Ich denke mal das liegt daran das es zwei unterschiedliche Hoster sind? Aber aus der sicht von meinem System ist es doch eig. nur eine Verbindung zum proxy?

MfG

15.11.2014 - 18:00 Uhr

Es ist eine C# .Net 4.5 Anwendung, welche mir Neuigkeiten aus dem Netz laden soll um mir diese anzuzeigen.

Schmeißen tut er sie mir, wenn ich mit der "GetAsync" vom HttpClient die Infos laden will (wirft dabei jedoch das eine oder andere mal die Exception).

Ob das nun weiter hilft glaube ich aber eher nicht...

Ist es auch richtig, dass er pro "GetAsync" eine eigene TCP-Verbindung auf macht?
Bzw. ich finde keinen weg sie einzeln zu schließen... es geht nur wenn ich das Kompeltte Object (HttpClient) zerstöre...

MFG

15.11.2014 - 16:42 Uhr

Hallo -
ich habe ein Problem und komme einfach nicht weiter ich habe schon sämtlich Sachen ausprobiert doch nichts führte zum Erfolg evtl. hat einer von euch eine Idee?

Ich bekomme folgende Exception:> Fehlermeldung:

Die Verbindung mit dem Remoteserver kann nicht hergestellt werden.
bei System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
bei System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat X.X.X.X:X
bei System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult)
bei System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)

Das ganze passiert willkürlich, daher ich kann nicht genau sehen/sagen wann es passiert.

Ich dachte erstmal das es evtl. daran liegen würde das ich zu viele TCP/IP-Verbindungen öffne, doch daran scheint es nicht zu liegen.. Der Remoteserver ist auch ohne Probleme erreichbar.

MfG

13.11.2014 - 14:44 Uhr

Vielen Dank - Das Routing in Windows ist nicht mein Problem.. eher das Routing in der C# .Net Anwendung wie ich sage das er die IP nehmen soll.

MfG

12.11.2014 - 23:45 Uhr

So ist es -
Die Karten im PC besitzen jeweils ihr eigenes Subnet, welche ebenfalls ihren eigenen Internetanschluss haben. Nun möchte ich einer C# .Net Anwendung sagen welche Karte sie nutze soll um ins Internet zu kommen. Momentan wird der weg eher zufällig vom System gewählt (nimmt scheinbar den momentan am besten geeigneten Ausgang).

MfG

08.11.2014 - 18:55 Uhr

Hallo -

ich frage mich ob es möglich ist den Traffic meiner Anwendung auf eine bestimmte Netzwerkkarte umzulenken? Für die Kommunikation nutze ich die 'HttpClient' Klasse.
Ich habe bisher nichts brauchbares finden könne, vielen Dank.

MfG

08.10.2014 - 15:23 Uhr

Alles klar ich schau mir das dann mal mit Services an -

Im Prinzip soll die Seite nur dazu dienen Tasks zu verwalten => Daher starten/stoppen und um
Einstellungen vorzunehmen.

Wenn ich das richtig versanden habe muss ich eine "Haupt"-Seite erstellen und einen "Service" der mehrfach startbar ist und den aufgetragenen Job erledigt?

MfG

08.10.2014 - 14:29 Uhr

Hallo -
ich habe bisher eher wenig mit dieser Web-Technology zu tun gehabt und bin mich momentan am einlesen.
Ich finde jedoch nichts dazu, wie ich Variablen erstelle die immer existieren daher auch wenn niemand die "Page" besucht.
Als Beispiel: Benutzer betritt die Seite startet eine intensive Aufgabe (Task wird gestartet) er verlässt die Seite und die Task sollte weiter laufen.

MfG

30.09.2014 - 09:45 Uhr

Danke erst einmal für die schnelle Antwort =) -
Ich habe es jedoch auch versucht, wenn ich es in der Main-UI Erstelle doch auch ohne erfolg..

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public class LogData : INotifyPropertyChanged
    {
        public LogData(string text) { Message = text; }
        private string _Message = string.Empty;

        public string Message
        {
            get { return _Message; }
            set{
                if (value != _Message){
                    _Message = value;
                    OnPropertyChanged("Message");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void _OnPropertyChanged(Object propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(Convert.ToString(propertyName)));
        }
        
        protected void OnPropertyChanged(Object propertyName)
        {
            if (PropertyChanged != null)
                Program.MyForm._sync.Post(_OnPropertyChanged, propertyName);
        }
    }

    public partial class Form1 : Form
    {
        public WindowsFormsSynchronizationContext _sync = new WindowsFormsSynchronizationContext();
        public Form1() { InitializeComponent(); }
        private BindingList<LogData> logmessages = new BindingList<LogData>();
        private void button1_Click(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() =>
            {
                logmessages.Add(new LogData("Message"));
            });
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            dataGridView1.DataSource = logmessages;
        }
    }
}

Oder habe ich hier noch einen Fehler gemacht?

PS: Das

EventArgs

muss ich noch entfernen... stammt noch von der alten Lösung.

30.09.2014 - 08:59 Uhr

Ich habe so ziemlich das selbe Problem aber verstehe die Lösung dafür nicht so ganz...

public class MyEventArgs : EventArgs, INotifyPropertyChanged
{
	public String _Message;
	public MyEventArgs() { }

	public MyEventArgs(String Message)
	{
		this.Message = Message;
	}

	public String Message
	{
		get { return _Message; }
		set
		{
			if (value != _Message)
			{
				_Message = value;
				OnPropertyChanged("Message");
			}
		}
	}

	public event PropertyChangedEventHandler PropertyChanged;
	protected void _OnPropertyChanged(Object propertyName)
	{
		if (PropertyChanged != null)
		{
			PropertyChanged(this, new PropertyChangedEventArgs(Convert.ToString(propertyName)));
		}
	}
	
	public SynchronizationContext _sync = new WindowsFormsSynchronizationContext();
	private void OnPropertyChanged(String info)
	{
		_sync.Post(_OnPropertyChanged, info);
	}
}

Das ist meine verwendete Klasse, diese binde ich in der GUI an einem DataGridView.

DataGridView.DataSource = BindingList<MyEventArgs>

Dennoch wird mir der Fehler geschmissen "Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement...."

Kann mir evtl. wer erklären wieso?

Mit freundlichen Grüßen

19.04.2014 - 13:40 Uhr

Danke werde ich mir heute mal durchlesen - Wobei ich eig. weiß was es sein sollte.

Habe mich allerdings auch vertan ich benutze MySqlBulkLoader mit der load-Methode.

Da SqlBulkCopy für MS Datenbanken ist und nicht für MySql 😦

19.04.2014 - 13:22 Uhr

Ja ich bin mir sicher aber habe gerade das hier gelesen
MDSN SqlBulkCopy

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

Heisst für mich das die Klasse/Instanz zwar Thread-safe ist aber nicht wenn ich mehrere davon erstelle... daraus schließe ich dann auch das ich effektiv nur eine Verbindung benötige da ich sowieso nicht Parallel einfügen kann?

Oder es gibt irgendeine Einstellung am MySql-Server wo ich etwas einstellen kann das es Funtkioniert?

18.04.2014 - 22:38 Uhr

Danke - habe es weitestgehend versucht so zu implementieren und läuft soweit auch ganz okay.
Jedoch mit dem Resultat das der MySqlBulkLoader bei der load-Methode oft eine exeption wirft.

Fehlermeldung:
MySql.Data.MySqlClient.MySqlException (0x80004005): Deadlock found when trying to get lock; try restarting transaction

Jede Task hat seine eigene MySQL-Verbindung.

17.04.2014 - 15:06 Uhr

Dann verstehe ich nicht wie ich mein Problem sonst lösen soll wenn ich keine Threads/Tasks verwenden soll weil's ein NoGo ist.

Die DB-Einträge sind ja nur ein Teil davon was in der Task/Thread ablaufen soll.
Diese läuft normalerweise in einer Endlosschleife und pullt Daten von einem Webserver und trägt diese wiederum in die DB ein. Dabei möchte ich nicht nur eine Webseite abfragen sondern mehrere... was sollte ich denn sonst tun? Mehrere Anwendungen starten??

Das mit der DB habe ich schon verstanden das diese nicht Multi-Threading fähig ist und ich Bulk nutzen sollte bzw. auch machen werde, das ändert jedoch nichts daran das ich meiner Meinung nach Tasks/Threads benötige um das Problem zu lösen bzw. Parallel Webseiten abzufragen?

17.04.2014 - 13:24 Uhr

Ja - ich habe das Prinzip der Tasks wohl nicht richtig verstanden..

Ich dachte die CPU wird bis zum Limit beschäftigt dem ist aber nicht so er startet soviel Tasks wie er der CPU "zumutet" unabhängig davon wie anspruchsvoll die Task ist 😕. Ich dachte jedoch das wenn eine Task im await geht das die nächste dran kommt.

Für mein vorhaben muss ich wohl einen eigenen kleinen Scheduler coden.

Preparen meinst du die DB oder die Methode prepare des MySqlCommand?

16.04.2014 - 20:51 Uhr

Möglich das ich es nicht richtig verstehe, da ich erst neulich mit Tasks angefangen habe bzw. mich momentan immer noch darin einlese.

Evtl. mal ein größeres Beispiel meinerseits:

public class DBInsertClient
{
	public Task Routine;
	public CancellationTokenSource AsyncCancelTokenSource = null;
	
	public Boolean StartInsertDataBaseRoutine()
	{
		Routine = Task.Run(async () =>
				{
					using (MySqlCommand mySQL_CMD = new MySqlCommand("INSERT ......", Connection))
					{
						mySQL_CMD.Parameters.Add("?Value", MySqlDbType.UInt32).Value = 0;
						await mySQL_CMD.ExecuteNonQueryAsync(AsyncCancelTokenSource.Token);
					}
				}
				,(AsyncCancelTokenSource = new CancellationTokenSource()).Token);
		return Routine.Status == TaskStatus.RanToCompletion;
	}
}

Von dieser konstellation starte ich mehrmals die StartInsertDataBaseRoutine aber die die CPU steigt nicht in die höhe bzw. die Einträge dauern ewig (muss ich noch auf Bulk umschreiben) aber dies soll den Aufbau zeigen wie ich die Tasks erzeuge. Es wäre daher sehr nett, wenn mir wer das Beispiel so umgestellt das ich die Pattern nicht missbrauche?

16.04.2014 - 18:12 Uhr

Danke für die Antwort benutze nun auch Task.Run.

Aber im Bezug auf das async weiß ich nicht wie dies anders geregelt werden sollte... ohne dem kann ich in der Funktion keine Asynchronen aufrufe machen.

Oder sollte man dafür wieder eine Task erzeugen?

Parallel Programming with .NET: Task.Run vs Task.Factory.StartNew

Danke für den hinweis mit Bulk - hört sich vielversprechend an

16.04.2014 - 17:29 Uhr

Hallo -

ich habe ein Problem mit meiner Anwendung ich starte um die ~40 Tasks, welche in eine DB schreiben.

Die Tasks werden scheinbar nicht oder nur "sequenziell" ausgeführt.

Starte ich statt den Tasks stattdessen Threads werden viel mehr Datensätze in kürzerer Zeit in die DB geschrieben.

Nun wollte ich mal fragen wieso das so ist bzw. ob ich das ändern könnte?

Codebeispiel wie ich einen Task starte:

Task TestTask = new Task(async () =>
            {
			// Schreibe in eine DB
			}).Start();

MfG

01.04.2014 - 17:28 Uhr

Oha gar nicht gesehen, Danke - Läuft nun 😃

Andere frage weißt du ob es evtl. auch möglich ist Socks-Proxy zu nutzen?
Bzw. wie ich an den Socket des HttpClient's komme um es gegeben falls selber implementieren zu können?

01.04.2014 - 16:08 Uhr

Moin -

ich habe ein Problem und zwar schaffe ich es nicht das meine Anwendung den Proxy benutzt.

Codebeispiel von der Initialisierung des HttpClient's


            HttpClient WebClient = new HttpClient(
                MessageHandler = new HttpClientHandler
                {
                    AutomaticDecompression = DecompressionMethods.GZip,
                    Proxy = new WebProxy(new Uri("http://IP:Port")),
                    Credentials = new NetworkCredential("Benutzer", "Passwort"),
                    UseProxy = true
                }
                );

Beim Proxy handelt es sich um einen HTTP-Proxy, dieser ist auch verfügbar und funktioniert.

Ich hoffe ihr könnt mir hier weiter helfen, vielen lieben Dank 😃

Greetz