Laden...
Avatar #avatar-1907.png
Robert G myCSharp.de - Member
Entwickler München Dabei seit 12.04.2006 347 Beiträge
Benutzerbeschreibung

Forenbeiträge von Robert G Ingesamt 347 Beiträge

20.04.2006 - 11:45 Uhr

Das ich jetzt definitiv in Hintern gekniffen bin, weiß ich jetzt auch 😦. Aber ok, werde ich mir mal was anderes überlegen. Wo ist das Problem mit Marshal.GetDelegateFromBlaBla oder der Lib hinter dem Link oben? 🤔

20.04.2006 - 11:03 Uhr

Jet hat die komische Angewohnheit Strings in Doublequotes (#34) statt Singequotes (#39) zu setzen.
In FB, wie fast jedem (non-MS) DBMS, schließen Doublequotes kranke Bezeichnernamen ein. Es sind also KEINE Strings!

Das ist jetzt natürlich nur ein Schuss ins Blaue, da du nicht den SQL String gezeigt hast, der den Fehler auslöste... X(

btw:

Pruefung.name Like *

müsste

Pruefung.name Like '%'

heißen.
like '*' ist wieder so ein proprietäres MS-Ding. Was bei Jet ein * ist in richtigen DBMS ein %, ein ? ist ein _ .
Bin mir da jetzt aber nicht sicher, ich muss Jet zum Glück nicht oft anfassen. 😉

20.04.2006 - 10:54 Uhr

Attributverwendungen sind schon vom Prinzip her compile time konstant.
-> Iss nich 😉

Du kannst aber diese Lib, bzw die C# Sauce weiter unten ausprobieren. Damit kannst du Funktionen in .Net "dynamisch" linken. 😉
Möglich ist auch LoadLibrary, GetProcAddress + Marshal.GetDelegateFromFunction in .Net 2.0. Hinter den Bühnen wird die aber nicht viel anders machen können. 😉

19.04.2006 - 14:46 Uhr

Einem Array am nähesten kommt eine piepnormale List<T>.
Da sie stufenweise wächst muss nicht ständig umkopiert werden.
Beim Anlegen solltest du dem Contructor aber die gewünschte Größe übergeben, das spart unnütze Kopierereien beim ersten Füllen.

19.04.2006 - 14:32 Uhr

.Net Array haben eine konstante Größe, period.
Wenn du veränderliche Container brauchst, wären Arrays wohl sowieso eine schlechte wahl. (Außer man mag es ständig den ganzen Inhalt umherzukopieren 😉 )

19.04.2006 - 12:25 Uhr

Original von sheitman
Wenn sich die FAQ zu dem SQL Everywhere mal durchliest erkennt man, wofür das Produkt gedacht ist


>
Demnach wäre SqlServer für alles bestens geeignet, entweder der große oder der kleine.
Das ist so als ob man VW, BMW oder Audi fragen würde, wer die besten Autos baut... kopfschüttel

19.04.2006 - 10:31 Uhr

Ich konnte Joki ganz gut folgen, BIS FoxPro ins Spiel kam.
Das kann ich nun wirklich nicht nachvollziehen...

Zum interessanten Punkt in dem Thread: Es macht nicht immer Sinn Software nur deshalb einzusetzen weil MS drauf steht. Als lokale DB muss schon einiges zusammen kommen, bevor sich eine engine lohnt, die installiert werden muss.
Es muss noch vielmehr zusammenkommen bevor man dafür etwas installiert, was sich nie wieder restlos entfernen kann. Zumindest IMHO.
btw: Als lokale DB bezeichne ich strikt Single User & rein lokale Zugriffe. Also nicht entartete Geschichten wie Jet, dBase oder FoxPro, in der sich 5 Clients die gleiche Datenbankdatei im Netz wie wild gegenseitig um die Ohren werfen... 😕

Genau hier sind Systeme wie die vorgeschlagenen inproc DBMS (Wobei Firebird auch als voller Server laufen könnte ) genau in ihrem Element.
SQLX herzunehmen, weil man keine Lust hat den DAL DB-unabhängig zu machen kann durchaus ein Punkt sein, den man mit dem Kunden besprechen und auf die Art Kosten/Vorteile abwägen kann, aber irgendwie wirkt das nicht wirklich berauschend...
Bei wirklich aufwendigen Relpikationen wäre SQLX schon angebrachter, da man hier diese Features frei Haus bekommt. (SQLX kann doch Replikationen, oder? 🤔 )

19.04.2006 - 09:45 Uhr

Probier's doch einfach mal... 😁

19.04.2006 - 02:19 Uhr

Original von svenson
Hey cool, wußte gar nicht dass das in 2.0 geht. Problem war ja bisher immer den Zeiger aufrufbar zu machen. Ein kleine Funktion und es funzt, wie nett.

Aber Vorsicht, du hast bei marshal.GetDelegateFr5000Zeichen kaum eine Möglichkeit das dynamische Linking zu beinflussen.
Du kannst keine CallingConvention übergeben, was es bei allen Funktionen != stdcall ziemlich über abkacken lassen wird. 😉

Aber verrat mir mal, wie du unter 1.1 das Assembly dynamisch gebaut hast. Die Lösung hab ich ja noch nirgends gesehen...

Hast du keinen Reflector? 😁

Ich schon -> ich habe gerade die Chrome Assembly durch den FileDisassembler gescheucht und ein paar grobe Patzer ausgebügelt (Damals war ich noch ziemlich neu in Chrome und wollte alle kranken Features austesten g ).
Es war nicht falsch, hatte aber zuoft GetParameters von Delegate.Invoke abgefragt...

C# hat kein Design By Contract, also habe ich die auch rausgeworfen...
Willst du die Prüfungen haben, einfach die Debug Assembly aus dem Archiv oben in den Reflector jagen und die Pre/Post Assertions rauskopieren.
Die invariants auch...

Hier die C# 1.1 Sauce (die overloads nehmen wohl am meisten Platz weg g):

namespace DynamicCodeHelpers
{
  using System.Threading;
  using System.Collections;
  using System.Reflection.Emit;
  using System.Reflection;
  using System;
  using System.Runtime.InteropServices;

  public sealed class FunctionLoader
  {
    static Hashtable delegatesByFunctionPointer = new Hashtable();
    static ModuleBuilder moduleBuilder;

    
    static FunctionLoader()
    {
      AssemblyName assemblyName = new AssemblyName();
      assemblyName.Name = "DynamicFunctionTempAssembly";
      AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName,
                                                                                 AssemblyBuilderAccess.Run);
      moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name);
    }

    static MethodInfo BuildMethod(Type delegateType,
                                  int functionPointer,
                                  CallingConvention callingConvention)
    {
      MethodInfo invocationCall = delegateType.GetMethod("Invoke");

      ParameterInfo[] parameters = invocationCall.GetParameters();
      Type[] parameterTypes = new Type[parameters.Length];

      for (int i = 0; i < parameters.Length; i++)
      {
        parameterTypes[i] = parameters[i].ParameterType;
      }

      TypeBuilder typeBuilder = moduleBuilder.DefineType(delegateType.Name + functionPointer);

      MethodBuilder methodBuilder = typeBuilder.DefineMethod(invocationCall.Name,
                                                             MethodAttributes.Static | MethodAttributes.Public,
                                                             invocationCall.ReturnType,
                                                             parameterTypes);
      ILGenerator ilGen = methodBuilder.GetILGenerator();

      for (int i = 0; i < parameters.Length; i++)
      {
        ilGen.Emit(OpCodes.Ldarg, i);
      }

      ilGen.Emit(OpCodes.Ldc_I4, functionPointer);
      ilGen.EmitCalli(OpCodes.Calli,
                      callingConvention,
                      invocationCall.ReturnType,
                      parameterTypes);

      ilGen.Emit(OpCodes.Ret);

      return typeBuilder.CreateType().GetMethod(invocationCall.Name);
    }

    public static Delegate CreateDelegate(int functionPointer,
                                          Type delegateType,
                                          CallingConvention callingConvention)
    {
      lock (typeof(FunctionLoader))
      {
        if (delegatesByFunctionPointer.ContainsKey(functionPointer))
        {
          return (Delegate)delegatesByFunctionPointer[functionPointer];
        }

        MethodInfo finalMethod = BuildMethod(delegateType, functionPointer, callingConvention);
        
        Delegate result = Delegate.CreateDelegate(delegateType, finalMethod);
        delegatesByFunctionPointer.Add(functionPointer, result);

        return result;
      }
    }

    public static Delegate CreateDelegate(int functionPointer, Type delegateType)
    {
      return CreateDelegate(functionPointer, delegateType, CallingConvention.StdCall);
    }

    public static Delegate CreateDelegate(string libraryName, string functionName, Type delegateType)
    {
      return CreateDelegate(libraryName, functionName, delegateType, CallingConvention.StdCall);
    }

    public static Delegate CreateDelegate(uint libraryHandle, string functionName, Type delegateType)
    {
      return CreateDelegate(libraryHandle, functionName, delegateType, CallingConvention.StdCall);
    }

    public static Delegate CreateDelegate(string libraryName,
                                          string functionName,
                                          Type delegateType,
                                          CallingConvention callingConvention)
    {
      return CreateDelegate(LoadLibrary(libraryName),
                            functionName,
                            delegateType,
                            callingConvention);
    }

    #region Kernel32 imports
    
    [DllImport("kernel32.dll")]
    static extern int GetProcAddress(uint libraryHandle, string functionName);
    [DllImport("kernel32.dll")]
    static extern uint LoadLibrary(string libraryName);

    #endregion
    
    public static Delegate CreateDelegate(uint libraryHandle,
                                          string functionName,
                                          Type delegateType,
                                          CallingConvention callingConvention)
    {
      return CreateDelegate(GetProcAddress(libraryHandle, functionName),
                            delegateType,
                            callingConvention);
    }
  }
}

Falls gewünscht kann ich es auch noch für DynamicMethods aus 2.0 umschreiben. Erspart die dyn Asembly. 😉

18.04.2006 - 19:25 Uhr

Schaue dir mal DataSet.Merge an. 😉

18.04.2006 - 18:38 Uhr

Original von svenson
Ums gleich vorwegzuschicken: Späte Bindung mit Nicht-COM-DLLs geht eigentlich nur über einen managed C++-Wrapper.

Das ist nicht ganz richtig.

Die Beispiele benutzen diesen Delegate typen...

delegate int AddMethod(int left, int right);

und die kleine, native Beispiel-DLL aus Delphi:

library NativeSampleLib;

function Add(left, right : Integer) : Integer; stdcall;
begin
  result := left + right;
end;

exports
  Add;

end.

*In .Net 2.0 gibt es Marshal.GetDelegateFromFunctionPointer:

[DllImport("kernel32.dll")]
static extern UInt32 LoadLibrary(string libraryName);
[DllImport("kernel32.dll")]
static extern IntPtr GetProcAddress(UInt32 libraryHandle, string functionName);

static AddMethod DotNet20()
{
  UInt32 libraryHandle = LoadLibrary("NativeSampleLib");
  IntPtr functionPointer = GetProcAddress(libraryHandle, "Add");

  return Marshal.GetDelegateForFunctionPointer(functionPointer,
                                               typeof(AddMethod)) as AddMethod;
}

*In 1.1 muss man sich dynaisch eine Assembly bauen, ich habe gerade mal eine ziemlich eingestaubte Solution rausgekramt und gegen 1.1 kompostiert.[1]
Peverify aus .net 1.1 sagt sie ist OK, also denke ich mal, dass ich die richtige Build Config erwischt habe. 😁 (Habe hier nur noch VS2005)
Ich habe nur den FunktionLoader hineinkompiliert, sollte also recht übersichtlich sein. g
Der Code würde für .Net 1.1 dann so aussehen:

private static AddMethod DotNet10()
{
  return FunctionLoader.CreateDelegate("NativeSampleLib",
                                       "Add",
                                       typeof(AddMethod)) as AddMethod;
}

btw:
Im angehängten Archiv sind 2 Ordner, die Release version ist ohne class contract kompiliert. Somit ist sie schneller aber fast ohne Prüfungen...

[1]Sie ist in Chrome geschrieben, weshalb sie für euch wohl nur in binärer Form interessant sein wird 😉

18.04.2006 - 12:37 Uhr

Du hast da einen Event deklariert und du bist hier in eine klassische Compiler magic Falle gerannt. 😁

Wenn du das hier schreibst:

public event DelegateTyp MyEvent;

wird eigentlich das hier daraus:

DelegateTyp myEvent;

public DelegateTyp MyEvent
{
   add   { myEvent += value; }
   remove{ myEvent -= value; }
}

Innerhalb der Klasse wird der Compiler das private Feld des Delegaten benutzen.
Deshalb geht dort das hier:

if(MyEvent != null)
  blabla;

Eigentlich wird das hier kompostiert:

if(myEvent != null)
  blabla;

Der öffentliche Event hat, wie für Events üblich nur add und remove als Accessors.[1]
Deshalb kannst du in der Ableitung oder in anderen Typen nur noch Delegaten hinzufügen oder entfernen.

Es gibt 2 Lösungen für dein Problem, eine ist das übliche Event pattern in .Net, die andere ist ein übler Hack-around. 😉
*

public event DelegateTyp MyEvent;
protected virtual OnMyEvent(SomeEventargsDescendant eventArguments)
{
  if(MyEvent != null)
    MyEvent(this, eventArguments);
}
protected DelegateTyp myEvent;

public DelegateTyp MyEvent
{
   add      { myEvent += value; }
   remove{ myEvent -= value; }
}

Die 2. Lösung gibt dir in Ableitungen direkten Zugriff auf den Delegaten, die erste lässt dich in Ableitungen nur den Deleagten feuern ohne direkten Zugriff zu gewähren.
In 99.9P% aller Fälle sollte die 2. Lösung als "pfui deivel" eingestuft werden. 😉

[1]Events sind neben Properties Abstraktionen von Feldern.
Properties haben get_PropertyName/set_PropertyName, Events haben add_EventName/remove_EventName.

Edit1&2: noch mehr Copy&Waste Fehlerchen... 8o

18.04.2006 - 11:45 Uhr

Original von Ishildur
Ich habe jetzt absolut alles deinstalliert, es geht trotzdem nicht! Das wars dann wohl SQL - Express... 😛 Es gab auch andere Vorschläge außer einer dicken MDAC/MSSQL-Installation.
Es gibt außerdem noch Nexus DB, nicht kostenlos aber auch ein nettes inproc/standalone DBMS.

Probiere einfach mal die drei (bzw. 4 mit SQLX) aus und suche dir die aus, die dir am besten zusagt. 😉

18.04.2006 - 11:34 Uhr

Wird wohl etwas OT, aber das interessiert mich dann doch...

Original von FZelle
Wie immer meine bevorzugte Alternative SQLite. Ein paar kleine Fragen am Rande, da ich den Tip öfter gelesen habe:*Hast du es mal gegen FB embedded verglichen und hast daraufhin SqlLite gewählt? *Wenn ja was waren die Vorteile? *Wie groß ist die DLL (bzw. wieviele DLLs braucht man) ? *Sind SProcs und Trigger möglich?

Sorry, wenn ich dich so böse ausquetsche. 😁
Ich bin schon etwas neugierig und deren Seite gibt entweder nicht genug preis oder der Funktionsumfang (1 , 2) ist tatsächlich arg eineingeschränkt.

18.04.2006 - 10:01 Uhr

Sql Express scheint vlt ein etwas zu großer Vorschlaghammer zu sein.
Schaue dir mal Firebird an:
Deutsche Seite: http://firebird-datenbank.de/
Offizielle Seite: http://www.firebirdsql.org/

Im Gegensatz zu SqlExpress gräbt sich FB nicht metertief ins System ein. Was für deine Zwecke ideal sein kann, wäre der embedded Server. Das ist eine Clientbibliothek, die gleichzeitig den Server enthält.
Du kannst also eine FB Datenbank inproc öffnen OHNE dass irgendetwas außer deiner Anwendung installiert werden muss.
Außerdem ist es natürlich kostenlos.

Als Admin tool kann ich IB Expert empfehlen, gibt's auch als kostenlose Personal Edition.

btw: Im Jahre 2006 halte ich solche Antiquitäten wie MS Jet für etwas heikel...

edit: lol... Hatte 2005 getippt. 😁

18.04.2006 - 00:26 Uhr

Original von Programmierhans
ich verwende Path.Combine um Pfade zusammenzuzimmern. Ich auch.
Mono könnte es irgendwann für WasWeißIch geben, auf dem System könnten dann Pfade durch Grinse smileys getrennt werden. 😁

17.04.2006 - 22:05 Uhr

Der Code aus EntryTransformer hat nur 2 statische Spalten: Source und Status.
Alle Ports, die in allen übergebenen Entries vorhanden sind ergeben dann waagerecht die Spalten zwischen Source und Status (wie auf dem Screenie).
Wenn also auf Port XX das Signal zu Status 1 von 0815 kam wirst du das sehen:

Source XX    Status
0815   True 1
17.04.2006 - 21:57 Uhr

was ist deiner Meinung nach nicht richtig? HashTabellen werden da wie normale Container erklärt.
Ich finde man sollte hier nicht auf ein so tiefes Level herabsteigen. Ein Anfänger hat ganz andere Probleme als die Wahl des optimalsten Contaiiners.
Ein Umsteiger von einer nativen Sprache wie C/C++, D, ADA oder Delphi könnte sicher mit den Begriffen etwas anfangen und würde sich über ein paar Infos zu den Pros und Contras der .Net Implementierung freuen.

Vllt wäre deshalb ein weiterführender Artikel ganz nett. Der zum Beispiel TreeSet und Dictionary vergleicht, damit der Leser sich das richtige Werkzeug für seine Aufgabe wählen kann.
Da du oben Megenoperationen erwähnt hast: Ich habe an einer Implementierung von PascalSets für .Net mitgebastelt. Du findest es hier. Ist vllt auch interessant. 😉

17.04.2006 - 21:37 Uhr

Ich habe ebenfalls eine uralte Lizenz von PS7, die ich mir vor 100 Jahren in einem Praktikum verdient habe.
Aber zu 90% benutze ich Paint.Net. Wenn ich mal 'nen Screenie, Avatar,... für ein Forum anpasse oder Icons zeichne sehe ich es einfach nicht ein solch ein überladenes Tool wie PS zu nehmen.
Paint.Net hat genau den funktionumfang, den ich miestens brauche, startet schnell und frisst mir nicht soviele Ressourcen weg. Man kann problemlos Paint.Net 10-mal geöffnet haben, versuch das mal mit PS. 😁

Außerdem ist es FreeWare. http://www.eecs.wsu.edu/paint.net/

17.04.2006 - 21:25 Uhr

Ich bin gerade zufällig über die FAQ zu dem Thread gekommen.

Auch wenn das jetzt etwas kleinkariert wirken mag, die Erklärungen in den FAQ sind nicht richtig und der Leser bekommt einen komplett falschen Eindruck von Dictionaries bzw. normalen array-/listenbasierten Containern.

Eine HashTable hat den Vorteil, dass sie nicht suchen muss um etwas zu finden.
Aus dem Hash des Schlüssels berechnet sich seine Position in der internen Datenstruktur. Das heißt wenn ich ein Dictionary<string, XXX> habe wird eine Suche á la:

XXX element;
if(dictionary.TryGetValue("Hallo", out element))
  gefunden!

Bei 10 Elementen genauso lange dauern wie bei 10 Mio Elementen.
Um in einem normalen Container effizient suchen zu können müsste man diesen erst sortieren. Aber selbst eine Binrarysearch ist verglichen zu einer HashTable ziemlich langsam. Wobei natürlich die Generierung des HashCodes aus "Hallo" schneller als bei einer 20MB Datei als Schlüssel passiert. 😁
Ein wenig relativieren muss man also schon. 😉

Vielleicht reicht das als kleine Anregung für den FAQ Artikel....

17.04.2006 - 20:55 Uhr

Moin Xero,
auch hierher verlaufen? 😁

Möglich wäre sowas hier:

static IList<Control> CreateStackedControls(Control container, int controlsToCreate, DockStyle dockStyle)
{
  IList<Control> result = new List<Control>(controlsToCreate);
  container.SuspendLayout();
  try
  {
    for (int i = 0; i < controlsToCreate; i++)
    {
      Control newControl = new TextBox();
      result.Add(newControl);
      newControl.Parent = container;
      newControl.Dock = dockStyle;
      newControl.Show();
    }

    return result;
  }
  finally
  {
    container.ResumeLayout(true);
  }

}

Was du bzw. ob du etwas mit dem Rückgabewert machst bleibt dir überlassen. Solange du nicht solchen ekligen Krempel wie FindComponent benutzt.... 😁

17.04.2006 - 20:01 Uhr

Benutzt du DDCs[1] wie DataSets/DataTable oder eigene Klassen?
Wenn du die Daten in eigen Klassen hälst musst du INotifyPropertyChanged implementieren, damit die UI über Änderungen im Model informiert wird.
Dadurch kann sie die verknüpften Controls aktualisieren.

Ein anderes Problem ist das Standard setting für DataBinding im VS. Standardmäßig wird das Model erst bei einer Validierung des Controls aktualisiert. Das wiedderum passiert in der Regel erst, wenn ein anderes Edit Control den Fokus erhält.
Du kannst dieses Verhalten beinflussen, wenn du im PropertyGrid auf DataBindigns\Advanced clickst und im folgenden Dialog Update Mode auf PropertyChanged setzt. (siehe screenie)
Jetzt wird das Model immer dann aktualisiert, wenn das Control ein Änderungsevent feuert. Eine PictureBox ist leider kein wirkliches EditControl. Deshalb kann es sich hier anders als zum Bleistift eine TextBox verhalten....

17.04.2006 - 19:30 Uhr

Hallo Jürgen,

vielleicht solltest du in deinem Profil den genauen Namen deiner IDE hinterlegen.
Ich las VS und nahm an, dass du die aktuelle Version (aka VS2005) benutzt.
Mit dem neuen .Net 2.0 kamen ein paar neue Spielzeuge dazu, mein Code besteht fast ausschließlich aus diesen Neuerungen... 🙁

Ich kann ihn aber auch problemlos so umformen, dass er .Net-1.1-tauglich ist. IMHO besser wäre es, wenn du eine neuere Version des VS oder die kostenlosen C# Express organisieren könntest.

Abfragen könntest du die Werte so: (reiner Pseudo code, der auch Parameter zum Filtern zeigen soll)

IEnumerable<Entry> FetchEntries(IDbConnection connection)
{
  using (IDbCommand command = connection.CreateCommand())
  {
    command.CommandText =
      "SELECT Source, " +
      "       Port, " +
      "       Status, " +
      "       Protocol " +
      "FROM   DeineTabelle " +
      "WHERE  X = :Y"; // beim Sql Server wäre das hier @Y

    IDataParameter y = command.CreateParameter();
    command.Parameters.Add(y);
    y.ParameterName = "Y";
    y.DbType = DbType.Int32;
    y.Value = 1;

    using (IDataReader reader = command.ExecuteReader())
    {
      LinkedList<Entry> result = new LinkedList<Entry>();
      while (reader.Read())
      {
        Entry entry = new Entry();
        entry.Source = reader.GetString(0);
        entry.Port = reader.GetString(1);
        entry.Status = reader.GetInt32(2);
        entry.Protocol = reader.GetString(3);

        result.AddLast(entry);
      }
    }
  }
  return result;
}

Werfe oben deine Connection rein und passe das SQL an.

So könntest du es aufrufen:

DataTable table = new DataTable("TransposedEntries";);

EntryTransformer transformer = new EntryTransformer();
transformer.LoadInto(FetchEntries(deineConnection), table);

Wie gesagt, das ist .Net 2.0 Code. Und meiner Meinung nach wäre 2.0 auch die idealere Plattform.

Falls du eine 1.1 Lösung haben willst, ließe sich das sicherlich problemlos anpassen. 😉

17.04.2006 - 18:57 Uhr

ups, habe 'sichtbar' statt 'unsichtbar' gelesen. Dann die Argumenation genau umdrehen. Es kommt dann nur Component in Frage. Ich hatte schon an euch gezweifelt. 😁
@Kuppi
First things first: Frohe Rest-Ostern erstmal...

Wenn du eine Komponente anlegen willst hast du in der Express Edition leider kein Template dafür[1].

Als Delphi-umsteiger stehst du unter Welpenschutz und ich erkläre es mal ausführlich. 😉
Du hast jetzt 2 Möglichkeiten:*Du legst eine neue Klasse an und leitest sie von Component ab.

public class YourComponent : Component
{}

Speicherst sie, schließt die Datei und betest, dass das VS erkennt dass es eine Komponente ist.
Wenn es das erkennt sollte sich sofort das Icon der Datei ändern.
Danach kannst du die Datei öffnen und der Designer erscheint.
Der Designer wird dann automatisch den nötigen Designer code anlegen.

*Du legst ein Usercontrol an und änderst den Vorfahren von UserControl zu Component. Auf die Art hast du gleich noch eine 2. Datei in der das VS den ekligen Designer code ablegt.

[1]Kann man in den Express SKUs eigene Templates definieren? Wenn ja könnte man ja schnell ein Component template vorbereiten. 😉

17.04.2006 - 15:31 Uhr

Nichts für ungut, aber ich habe jetzt seit 3 Jahren dieses Object Pascal (Delphi 7) am Hals und ich finds ehrlich gesagt zum kotzen. Tut mir leid. Ich finde die Syntax hässlich, die Logik verdreht und viel zu überbläht. Das erste was ich mache, wenn ich das Abi fertig habe, ist das Deinstallieren von Delphi 😄 Du musst dich nicht dafür entschuldigen, dass du kein Pascal magst. :lol:
Klar das dies nun nur noch wenig bis gar nichts mehr mit Delphi zu tun hat, aber die Sprache an sich, wird ja beibehalten. Chrome und Delphi haben nicht viel gemeinsam. Außer dass beide ziemlich abgewandelte Derivate des ursprünglichen ObjectPascal sind. Beide gehen auch in verschiedene Richtungen. Während sich die Delphi-Entwickler einen Kullerkeks freuen weil ihr stumpfsinniger single-pass Compiler so sackschnell ist, versucht der Chrome compiler so schlau wie möglich zu sein ohne soviel versteckte compiler magic zu benutzen wie Delphi.
Was mich auch ein wenig stören würde, ist, dass Chrome bzw. diese Add-Ins etc. kommerziell sind. Nicht dass ich was dagegen hätte, aber fürs Testen möcht ich keinen Cent ausgeben. Danach vielleicht 😉 Da du offensichtlich kein Pascalisti bist, sehe ich zwar nicht viel Sinn darin aber es gibt eine Demo. VS03/05 Standard vorausgesetzt. 😉

17.04.2006 - 14:56 Uhr

Ich benutze hauptsächlich Chrome

17.04.2006 - 13:54 Uhr

Original von juergen_190
Hallo,
Vielen Dank, das ist ja mal ein Anfang.
Das Problem ist, ich weiss vorher nicht, wie viele Destports exisitieren,
ich kann die natürlich vorher mit distuinct abfragen.
Es kann dann aber sein, das bei dem 1.Füllen eines Listviews 4 Destports da sind, beim nächsten mal sind es 20....?

Vielen Dank aber schon mal für deine Mühe

Jürgen

Es gäbe noch die Lösung über ITypedList, die Ausgabe erst in der Darstellung zu drehen. Aber das artet gerne in einem Krmpf aus, deshalb bekommst du von mir nur 'ne olle DataTable. 😜
Deine Daten ließen in folgende Klasse verpacken:

public class Entry
{
	string source;
	string port;
	int status;
	string protocol;

	public string Source
	{
		get { return source; }
		set { source = value; }
	}
	public string Port
	{
		get { return port; }
		set { port = value; }
	}
	public int Status
	{
		get { return status; }
		set { status = value; }
	}
	public string Protocol
	{
		get { return protocol; }
		set { protocol = value; }
	}
}

Da ich mir ziemlich sicher bin, dass du Entry anders haben wirst, habe ich die nächste Klasse generisch gebaut.

abstract class NestedDictionary<T, K, SK, S> : SortedDictionary<K, IDictionary<SK, IDictionary<S, T>>>
{
	public event Action<K> KeyAdded;
	public event Action<SK> SubKeyAdded;

	protected abstract K GetKey(T entry);
	protected abstract SK GetSubKey(T entry);
	protected abstract S GetStatus(T entry);

	public void Add(T item)
	{
		K key = GetKey(item);
		SK subKey = GetSubKey(item);

		IDictionary<SK, IDictionary<S, T>> subDictionary;
		if (!TryGetValue(key, out subDictionary))
		{
			subDictionary = new SortedDictionary<SK, IDictionary<S, T>>();
			Add(key, subDictionary);
			OnKeyAdded(key);
		}

		if (!subDictionary.ContainsKey(subKey))
		{
			subDictionary.Add(subKey, new Dictionary<S, T>());
			OnSubKeyAdded(subKey);
		}

		subDictionary[subKey].Add(GetStatus(item), item);
	}

	public void AddRange(IEnumerable<T> items)
	{
		foreach (T item in items)
		{
			Add(item);
		}
	}

	protected void OnKeyAdded(K key)
	{
		if (KeyAdded != null)
		{
			KeyAdded(key);
		}
	}

	protected void OnSubKeyAdded(SK subKey)
	{
		if (SubKeyAdded != null)
		{
			SubKeyAdded(subKey);
		}
	}
}

Hier ist die Version, wie ich ie weiter verwende.
Sie soll einfach pro Source IP ein weiteres Dictionary halten, dass den Port als Key benutzt.
Edit: Musste noch eins für den Status reinhängen
So kann pro Source,pro Port und pro Status auf die betreffenden Entries zugegriffen werden:

class PortEntriesBySource : NestedDictionary<Entry, string, string, int>
{
	protected override string GetKey(Entry entry)
	{
		return entry.Source;
	}

	protected override string GetSubKey(Entry entry)
	{
		return entry.Port;
	}

	protected override int GetStatus(Entry entry)
	{
		return entry.Status;
	}
}

Und last not least: Die eigentliche Klasse:

using IEntriesByStatus = IDictionary<int, Entry>;

public class EntryTransformer
{
	readonly PortEntriesBySource entriesBySource = new PortEntriesBySource();

	/// <summary>
	/// sortiertes Dictionary, um jeden Port genau einmal und sortiert halten zu können
	/// </summary>
	readonly IDictionary<string, object> allPorts = new SortedDictionary<string, object>();

	public IEnumerable<string> AllPorts
	{
		get { return allPorts.Keys; }
	}

	public EntryTransformer()
	{
		entriesBySource.SubKeyAdded += entriesBySource_SubKeyAdded;
	}

	void entriesBySource_SubKeyAdded(string source)
	{
		if (!allPorts.ContainsKey(source))
		{
			allPorts.Add(source, null);
		}
	}

	public void LoadInto(IEnumerable<Entry> entries, DataTable table)
	{
		entriesBySource.Clear();
		allPorts.Clear();

		entriesBySource.AddRange(entries);

		PrepareTable(table);
		FillTable(table);
	}

	void PrepareTable(DataTable table)
	{
		table.Clear();
		table.Columns.Add("Source", typeof(string));

		foreach (string port in AllPorts)
		{
			table.Columns.Add(port, typeof(bool));
		}
		table.Columns.Add("Status", typeof(int));
	}

	void FillTable(DataTable table)
	{
		foreach (KeyValuePair<string, IDictionary<string, IEntriesByStatus>> source in entriesBySource)
		{

			// HACK: hier sind die 2 Status codes (0 und 1) fix angelegt
			for (int status = 1; status > -1; status--)
			{
				DataRow row = table.NewRow();
				row["Source"] = source.Key;
				row["Status"] = status;

				foreach (string port in AllPorts)
				{
					row[port] = false;

					IEntriesByStatus entriesByStatus;

					if (source.Value.TryGetValue(port, out entriesByStatus))
					{
						row[port] = entriesByStatus.ContainsKey(status);
					}
				}

				table.Rows.Add(row);
			}
		}
	}
}

Ich habe es mit den Beispieldaten aus dem ersten Beitrag probiert und einen Screenie aus dem Debugger angehängt. 😉

16.04.2006 - 21:23 Uhr

Original von v1vec
guten abend
zu ostern nur ne kurze frage:
wie kann ich bei einer list<> auf das erste element zugreifen?
gibts da eine äquivalente funktion zu .begin() aus der stl? List<T> ist arraybasiert!
Ein First, Begin,... ist deshalb nicht nötig. Du kannst sie aber nicht so benutzen wie du es bei der Liste aus der STL gewohnt bist. Arraybasierte Container sind Speicherfresser wenn man sie zuoft vergrößert. (Außer du weißt vorher genau wieviele Elemente es werden...)
Das .Net-Äquivalent zur STL list wäre die LinkedList<T>. 😉

16.04.2006 - 19:58 Uhr

Original von Cali271
hat sich gerade erledigt! Das mag schön für dich sein...
Jemand, der hier nach dem Problem sucht, ürde sich sicher über deine Lösung freuen. Ein Forum ist immer Geben und Nehmen. 😉

16.04.2006 - 18:41 Uhr

ist sicherlich auch fast eine philosophische Frage. Gibt sogar ne philosophische Frage als Antwort...
Angenommen du hast Klasse1 in deiner Datei und verwendest jetzt die Datei in 2 Bibliotheken.
Irgendwann, wenn deine Projekte etwas zusammenwachsen und du beginnst Bibliotheken zwischen ihnen zu teilen wirst du bemerken, dass du 2-mal Klasse1 lädst. Einmal aus der erst Lib und einmal aus der zweiten. Beide heißen gleich, sind aber NICHT die gleiche Klasse. Kurz gesagt: Alle Libs, die diese Datei benutzen, sind absolut inkompatibel zueinander.

Wenn du weniger Libs ausliefern willst bietet es sich an IlMerge im AfterBuild-Event der Release config zu verwenden um die Lib mit Klasse1 und die benutzende Lib zu verschmelzen.
Auf die Art musst du später nur eine andere Build Config wählen, wenn du Klasse1 in einer eigenen Lib brauchst.
Nun die frage: Womit schießt du dir wohl eher selbst in den Fuss? Die Verknüpfung auf die .cs oder indem du es trennst und verschmilzt wannimmer du es für richtig hälst?

Ich muß mich möglicherweise erst daran gewöhnen, in Delphi wars halt anders. Delphi32 mit "normalen" .Net-Sprachen[1] zu vergleichen ist ziemlich heikel.
Der Delphi compiler konsumiert eigentlich keine .pas-Dateien sondern .dcu-Dateien, die eine Art Zwischenkompilat darstellen. Diese sollte man wiederum in Packages gruppiert haben, falls der gleiche Fall wie oben eintritt: Man braucht zur Laufzeit die Klassen der Unit in mehreren binaries, die gleichzeitig geladen werden.
In Delphi32 kannst du bei einer Echse/DLL einfach alles hineinkompilieren, das ist in .Net nicht so einfach möglich, da hier der Compiler keine Kontrolle über die Runtime hat. 😉

[1]Also nicht Delphi.Net 😉

15.04.2006 - 15:18 Uhr

Original von FantaMango77
Das schöne an Namenskonventionen und Coding Guidelines ist, dass man wunderbar und unendlich lange darüber diskutieren und streiten kann.
Was aber immer wieder vergessen wird, ist, dass die verwendeten Konventionen meistens reine Geschmacksache sind. Die entstehenden Diskussionen verlieren sich meistens in belanglosen Details. Und der Sinn und Zweck von Konventionen wird dabei schnell vergessen. Eines der schönen Dinge an .Net ist, dass wenigstens die öffentliche Schneittstelle von APIs durch MS Konventionen gut abgedeckt wird. (Auch die obere deckt sich mit den MS Guidelines was Typennamen und öffentliche Bezeichner angeht).
So sind hässliche API nur noch sehr selten. 🙂

Mir ging es nur darum, dass sich da wirklich jemand hingesetzt hat und ein Dokument aufgsetzt hat, das jeden Leser dazu verdammen würde so entstellte Felder zu lesen...

15.04.2006 - 11:57 Uhr

_Original von egrath_ch versuch mich an die Coding Guidelines von I-Design zu halten. Zu finden unter:

>

Bis auf m_[Feld] unterscheiden die sich auch nicht von den StiNo .Net API Guidelines. (Welche keine Konventionen für private Felder haben)
Sorry, aber m_BlaBla sieht ziemlich krank aus, erinnert mich immer an irgendwelche Ex-VB'ler, die das Wort "Member" 5.000-mal am Tag in den Mund nehmen, weil es so OOP-like klingt. 😉

Ich selbst folge der #d Konvention für Felder und schreibe sie klein.
Sonderzeichen und kryptische Präfixe haben IMHO nix in Bezeichnern zu suchen...

14.04.2006 - 22:33 Uhr

Du kannst direkt einen Type cast benutzen.
Ich habe gerade IntPtr in den Reflector geworfen und der zeigte mir, dass es eine Überladung für einen expliziten Cast von IntPtr zu Int32 gibt. 😉

14.04.2006 - 17:25 Uhr

Ich glaube ohne den Inhalt deiner createUser-Methode dürften wir auf unsere Kristallkugeln angewiesen sein oder vllt das Horoskop der Bildzeitung....

btw: Bin ich der einzige hier, der sich gerade fragt was aus dem fast elitären Status asynchroner Programmierung in der nativen Welt geworden ist? 🤔

Multithreading ist nichts, was man einfach mal eben so in seine App baut.
Du kannst damit plötzlich in Probleme rennen, die du mit dem bisher gezeigten Wissenstand (no offense) höchstwahrscheinlich nicht einmal erkennen kannst.

Dir wäre wahrscheinlich besser geholfen, wenn du lernst, wie du dieses Statement effizienter an deine DB schicken kannst. Multithreading ist keine Lösung für ineffiziente SQLs. 😉

13.04.2006 - 22:36 Uhr

Irgendwie konnte ich denk Sinn nicht ganz sehen, aber ich schreibe trotzdem wovon ich dachte, dass du es so haben willst.. ^^

Deine autonome Transaktion ist eigentlich ein böser Hack. Du fügst so dauerhaft Werte ein, auch wenn das eigentliche Insert kein Commit bekommt.

Der Schemaname dbo lässt vermuten, dass du von der SQL Server-Ecke kommst und schmerzlich "SELECT X FROM Inserted" vermisst, right? 😉

In Oracle kann man Werte innerhalb einer Session auch über mehrere Calls im Speicher halten indem man sie als Felder eines Packages deklariert.
Packages erlauben es auch diese Were privat zu deklarieren, so dass sie nur von deinen Methoden geändert werden können.

Hier mal der Beispiel code (jeweils jeden Code bereich in der Reihenfolge einzelnkompilieren):

create or replace package dbo.LogSample is
  subtype TPrimaryKey is tbschicht.aufid%type;

  procedure ApplyTemporaries;
  procedure AddTemporary(pId in TPrimaryKey);

end LogSample;
create or replace package body dbo.LogSample is

  type TPrimaryKeyList is table of TPrimaryKey;
  type TPrimaryKeyHashList is table of TPrimaryKey index BY binary_integer;

  /*
  private liste, die alle Ids enthält,
  die innerhalb eines (Multi-Record-)INSERTs eingefügt wurden
  */
  fTemporaryIds TPrimaryKeyHashList;

  -- wenn true, ändere nichts
  fLock boolean := false;

  procedure InsertSchicht(pId in TPrimaryKey) is
    AtvIds    TPrimaryKeyList;
    InsertIds TPrimaryKeyList;
  begin
    SELECT aufid BULK COLLECT
    INTO   AtvIds
    FROM   tbauftrag_z
    WHERE  aufid = pId
    and    iterminal = 1;
  
    if AtvIds.Count > 0 then
    
      SELECT aufid BULK COLLECT
      INTO   InsertIds
      FROM   tbauftrag_z
      WHERE  aufid_terminal = pId
      and    iterminal = 0;
    
      if InsertIds.Count > 0 then
      
        for i in AtvIds.First .. AtvIds.Last loop
          for j in InsertIds.First .. InsertIds.Last loop
            INSERT INTO tbSCHICHT (AUFID) values (InsertIds(j));
          end loop;
        end loop;
      
      end if;
    end if;
  end InsertSchicht;

  procedure AddTemporary(pId in TPrimaryKey) is
  begin
    if not fLock then
      fTemporaryIds(nvl(fTemporaryIds.Last, 0) + 1) := pId;
    end if;
  end AddTemporary;

  procedure ApplyTemporaries is
  begin
    if not fLock
       and fTemporaryIds.Count > 0 then
    
      fLock := true;
    
      for i in fTemporaryIds.First .. fTemporaryIds.Last loop
        InsertSchicht(fTemporaryIds(i));
      end loop;
    
      fLock := false;
    end if;
  
    fTemporaryIds.Delete;
  exception
    when others then
      fLock := false;
      fTemporaryIds.Delete;
      raise;
  end ApplyTemporaries;

end LogSample;
create or replace trigger dbo.tbSchicht_AI_AddTemp
  after insert on tbSchicht
  for each row
begin
  LogSample.AddTemporary(:new.AUFID);
end;
create or replace trigger dbo.tbSchicht_AI_ApplyTemp
  after insert on tbSchicht
begin
  LogSample.ApplyTemporaries;
end;

Der erste Trigger wird für jede Zeile eines Inserts ausgeführt und füllt die Liste im Package mit den Ids.
Der Zweite Trigger wird nach dem kompletten Insert[1] ausgeführt und sorgt dafür, dass alle temporären Ids abgearbeitet werden.

Am besten jagst du ein einfaches Insert mal durch den debugger und springst zeilenweise durch. Das sollte eigentlich genau erklären, was hier passiert. 😉
( Geht mit dem PL/SQL Developper sehr schön 🙂 )

Ich denke mal du hast deinen Code gekürzt bevor du ihn hier reingestellt hast. Wenn du noch Hilfe brauchst, wäre es wohl besser wenn du alles zeigst. 😉

btw: Wie du an InsertSchicht siehst, ist nicht viel übrig geblieben. Vllt siehstdu jetzt, das du da für alle AtcIds alle InsertIds Ids einfügen wolltest. 🤔

Kleiner Tip: wenn du Daten abfragst, veruche sie in einem Rutsch per Bulk collect in einen Array zu schieben.

for record in cursor loop
...
oder
fetch cursor into record

...sind arrrschlahm 😉

[1]also auch wenn du 100 Zeilen auf einmal einfügst

13.04.2006 - 18:24 Uhr

Borlands ECO würde relativ gut den Anforderungen entsprechen.
Es ist aber ziemlich tight in eine .Net 1.1 IDE verdrahtet (BDS2006), was es für die meisten Dinge heutzutage schlichtweg witzlos macht... X(

13.04.2006 - 18:17 Uhr

*Hashing ist, KEINE Verschlüsselung!
Hashing ist eine Einwege-Informationsreduzierung um entweder die Vergleichsgeschwindigkeit zu erhöhen oder damit man nicht auf Originaldaten schließen kann.

*.Nets GetHashCode liefert dir nur einen Int32
Das mag für die Macher der Dictionaries das Leben vereinfacht haben, reduziert aber den Informationsgehalt auf die gleiche Datenmenge, die 2 Zeichen in einem String einnehmen.

Könntest du aus 2 Zeichen einen 20MB Text wiederherstellen?[1] Ich nicht. 😄

[1]2 Zeichen, die nichtmal darin enthalten sein müssten, da GetHashCode nur sicherstellen muss, dass der gleiche Eingangsstring immer den gleichen Int32 generiert.

13.04.2006 - 17:59 Uhr

Original von Kostas
Hallo svenson,

ok, ich werde in Zukunft List verwenden weil diese Vorgehensweise die
gleiche ist wie sonst bei Klassen.

List<LieferantenAdresse> liAdressen = new List<LieferantenAdresse>();  

Man sollte sich immer mit dem kleinsten gemeinsamen Nenner zufriedengeben.
Verwendest du in deinem Code List<T> kannst du die Containerklasse später nur gegen Nachfahren von List<T> austauschen.
Bei IList<T> bleibst du kompatibel zu allen Implementierungen dieses Interfaces (also auch zu einem Array!).

Du solltest aber noch weiter gehen und in jeder Methode prüfen was du wirklich brauchst:*Reicht dir ein foreach -> IEnumerable<T> *Willst du auf Items prüfen oder welche hinzufügen/entfernen -> ICollection<T> *Brauchst du den Indexer -> IList<T> [1]

Plötzlich passt dein Code zu fast jeder Containerklasse, die dir im .Net Zoo vor die Füße kommen kann, du könntest also List<T> gegen LinkedList<T> ersetzen wenn du bemerkst, dass du viele Äderungen vornimmst und keinen Indexer brauchst.
List<T> ist keine Klasse in der man in einer großen Schleifen Items anhängen will. (Außer man weiß vorher ganz genau wieviele es werden)

[1]Wobei man so selten über einen Indexer auf die Daten gehen muss, das es schon oft ein Zeichen schlechten Design ist 😉

13.04.2006 - 17:30 Uhr

FTR:1.Es ist böse SQL Strings zusammenzufriemeln wenn man es nicht muss.
Es ist sehr böse Werte in den SQL String zu friemeln. 1.Wofür die alte ADO Connection? 🤔

Als abstrakter Bleistift wäre sowas möglich:

IEnumerable<string> GetTeamsByCategory(IDbConnection connection, int category)
{
  using(IDbCommand command = connection.CreateCommand())
  {
    command.CommandText =
      "SELECT Mannschaftsname " +
      "FROM   tblMannschaften " + 
      "WHERE  tblMannschaften.Kategorie = :Kategorie";
    
    IDataParameter categoryParam = command.CreateParameter();
    command.Parameters.Add(categoryParam);
    
    categoryParam.DbType = DbType.Int32;
    categoryParam.Value = category;
    
    LinkedList<string> result = new LinkedList<string>();
    
    using(IDataReader reader = command.ExecuteReader())
    {
       while(reader.Read())
       {
          resut.AddLast(reader.GetString(0));
       }
    }
  }
  
  return result;
}
using(IDbConnection deineConnection = new WasWeißIchConnection("connection string"))
{
  foreach(string team in GetTeamsByCategory(deineConnection, 2))
    Console.WriteLine(team);
}
13.04.2006 - 17:10 Uhr

_Original von Programmierhans_Grundsätzlich richtig für Windows-Plattform....
Environment.NewLine ist aber trotzdem besser (dies liefert unter Windows genau \r\n ... unter anderen OS aber den Plattform abhängigen String) Genau.
"\r\n" ist genauso böse wie: pfad + "\" + datei

Beides absolut plattformabhängig... 🙄

12.04.2006 - 23:34 Uhr

Original von der Marcel
Hi Pedro_15!

Original von Pedro_15
Wenn ihr Threads programmiert, benutzt ihr eigene Threadklassen dafür?
Wenn ja wie realisiert ihr die invoke methoden?

Ist das dein ernst? 😁

Für Threads benutzt man System.Threading.Thread oder unter .Net2.0 den Backgroundworker, wobei mir System.Threading.Thread besser gefällt.

Moin Marcel,
Deine Antwort liest sich ein wenig hochnäsig. 😉 Vor allem, da sie nicht wirklich hilfreich war. (No offense 😉 )

BackgroundWorker fällt bei mir unter den Neuerungen, die eingeführt wurden, damit selbst Ex-VB'ler mit Multithreading klarkommen.
Pedros Frage ist durchaus berechtigt und IMHO hat er recht.
Wenn du einem Thread Werte übergeben willst kannst su sie entweder über eine lokale anonyme Methode übergeben[1] oder, viel sauberer, man legt sich eine Klasse an, der man die Werte übergeben kann.

Das Synchronisieren ist leider nicht besonders hübsch möglich:
Du kannst entweder Events innerhalb deines Threads feuern und der Konsument kümmert sich um die Synchronisierung mit der GUI, oder du übergibst eine Referenz auf ein Control an deine Klasse. Dadurch könntest du Events im GUI Thread feuern.

Ehrlich gesagt gehört asynchroner Code zu den Dingen, die ich lieber in Chrome erledige als in C#, da generiert der Compiler diese Klasse wenn man eine Methode als async deklariert. 🙂

[1]somit kann man unabhängig von den Parametern alle Werte im scope benutzen.

12.04.2006 - 18:49 Uhr

Oki, mein Fehler. Ich hätte testen sollen was ich hier tippe. X(

Control.Invoke mag es anscheinend gar nicht wenn man ihm eine reine Methode vorwirft.
Du musst ihn an der Stelle wieder "zu Fuss" mit einem Delegaten verpacken:

TextBox1.Invoke(new MethodInvoker(test));
12.04.2006 - 18:26 Uhr

Original von sbertl000
ok ich habe deinen Code probiert, der funktioniert aber nicht. Oder mache ich etwas falsch (wert ist in diesem Fall die textBox) D'oh! 8o
Habe nicht gesehen, dass du noch VS03 und somit .Net 1.1 benutzt....
C#1.1 kann noch nicht autom. den richtigen Delegaten generieren (hier Threadstart) und anonyme Methoden gab es damals auch noch nicht.

So könnte die "klassische" Lösung aussehen:1.eine Methode, die im Thread rennt (AsyncCall) 1.eine Methode, die an den GUI Thread gehängt werden kann (test)

private void thread1()
{
  Thread t = new Thread(new ThreadStart (AsyncCall));
  t.Start();
}

private void AsyncCall()
{
      TextBox1.Invoke(test);
};

private void test()
{
   TextBox1.Text = "testtest";
}
12.04.2006 - 18:10 Uhr

Original von sbertl000
oh mann das sieht ja (für mich) kompliziert aus. könntest du mir vieleicht einen tipp zu meinem beispiel geben? Habe ich eigentlich...
btw: Antworte bitte direkt auf den Beitrag, auf den du dich beziehst. Sonst sieht man nicht wen du überhaupt meinst.... 🤔

*Falls* du mich meintest: Wo hast du denn genau Probleme?

12.04.2006 - 18:01 Uhr

Du darfst nicht von einem anderen Thread auf GUI Controls zugreifen.
Die GDI+ ist nicht thread safe, deshalb prüft SWF ziemlich genau ob ein call vom richtigen Thread kam. 😉

Ab Control ist die Methode Invoke verfügbar. Der kannst du eine Methode und (optional) Parameter übergeben. Diese Methode wird dann im GUI-Thread ausgeführt und alles ist in Butter. 🙂

Bleistift:

private void thread1()
{
  ThreadStart asyncCall = delegate
  {
      TextBox1.Invoke(test);
  };

  Thread t = new Thread(asyncCall);
  t.Start();
}

private void test()
{
   TextBox1.Text = "testtest";
}

oder du schaust dir einfach mal das hier an. 😉

12.04.2006 - 17:50 Uhr

Original von lindesbs
Klasse ! userControls war der richtige hinweis! Danke Falls es gewünscht ist wirklich Forms auf ein Form zu packen:
Schaue dir mal die Property TopLevel an. Setze sie auf false und du kannst ein Form in ein anderes Control stecken. 😉