roker002
Commander
- Registriert
- Dez. 2007
- Beiträge
- 2.075
Ich habe eine Frage:
Hat MS SQL CLR Extended Procedures probleme mit Multithreading?
Ich versuche nähmlich eine Endlosschleife mit UdpClient.Receive. Sobald was ankommt, sollte es in die Datenbank mittels SqlCommand geschickt werden. Es funktioniert alles innerhalb einer Exe, sobald aber CLR Funktion ausgeführt wird, geht beim Receive nichts mehr. Der Thread läuft weiter im hintergrund.
Ich dachte, wenn ich schon SqlConnect und Command im Hauptthread erstelle sollte es ja funktionieren. Tut es aber trotzdem nicht.
Bin deswegen jetzt überfragt.
Alles in einem ist es in eine Singleton Klasse verpackt. Sobald eine Send ausgeführt werden sollte, wird die Instanz erstellt, die auch mehrere BackgroundWorker erstellt die auf bestimmten Ports horchen. Ab da laufen im Hintergrund die Receive Threads und man kann (ohne dass ganze Prozess beblockt wird) auch parallel Nachrichten versenden.
Es ist auch sehr wichtig, dass Receive bis zum abbruchpunkt immer ausgeführt wird.
Ich verwende den SqlContext für die Abfragen. Daher ist mir eh nahliegend, dass SqlCommand nicht über mehrere Threads SQL Abfragen versenden kann.
EDIT
Offenbar kann eine Kontext Verbindung nicht hergestellt werden, wenn diese aus dem anderen Thread hergestellt wird. Ich konnte mit einer Trusted Connection eine Verbindung aufbauen.
Hat MS SQL CLR Extended Procedures probleme mit Multithreading?
Ich versuche nähmlich eine Endlosschleife mit UdpClient.Receive. Sobald was ankommt, sollte es in die Datenbank mittels SqlCommand geschickt werden. Es funktioniert alles innerhalb einer Exe, sobald aber CLR Funktion ausgeführt wird, geht beim Receive nichts mehr. Der Thread läuft weiter im hintergrund.
Ich dachte, wenn ich schon SqlConnect und Command im Hauptthread erstelle sollte es ja funktionieren. Tut es aber trotzdem nicht.
Bin deswegen jetzt überfragt.
Alles in einem ist es in eine Singleton Klasse verpackt. Sobald eine Send ausgeführt werden sollte, wird die Instanz erstellt, die auch mehrere BackgroundWorker erstellt die auf bestimmten Ports horchen. Ab da laufen im Hintergrund die Receive Threads und man kann (ohne dass ganze Prozess beblockt wird) auch parallel Nachrichten versenden.
Es ist auch sehr wichtig, dass Receive bis zum abbruchpunkt immer ausgeführt wird.
Ich verwende den SqlContext für die Abfragen. Daher ist mir eh nahliegend, dass SqlCommand nicht über mehrere Threads SQL Abfragen versenden kann.
EDIT
Offenbar kann eine Kontext Verbindung nicht hergestellt werden, wenn diese aus dem anderen Thread hergestellt wird. Ich konnte mit einer Trusted Connection eine Verbindung aufbauen.
Code:
private void CreateBackgroundWorker(UdpParameters param)
{
var worker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true };
worker.DoWork += new DoWorkEventHandler(_DoWork);
worker.ProgressChanged += new ProgressChangedEventHandler(_ProgressChanged);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_RunWorkerCompleted);
this.BgWs.Add(worker);
this.Connections.Add(param);
worker.RunWorkerAsync(param);
}
private void _DoWork(object sender, DoWorkEventArgs ev)
{
var param = ev.Argument as UdpParameters;
BackgroundWorker w = sender as BackgroundWorker;
IPEndPoint ep = null;
if (param != null)
{
try
{
ep = new IPEndPoint(IPAddress.Any, param.Port);
while (w.CancellationPending == false)//StopReceiving == false && interrupted < 10)
{
var array = new Byte[0];
try
{
array = param.Client.Receive(ref ep);
}
catch (SocketException e)
{
w.ReportProgress(0, new AsyncSendArguments { Error = e, IPAddress = ep, Version = param.Version });
break;
}
catch (ObjectDisposedException)
{
throw;
}
catch (Exception e)
{
w.ReportProgress(0, new AsyncSendArguments { Error = e, IPAddress = ep, Version = param.Version });
break;
}
w.ReportProgress(0, new AsyncSendArguments { Message = array, IPAddress = ep, Version = param.Version, Operation = DbOperation.Receive });
}
}
catch (Exception e)
{
w.ReportProgress(0, new AsyncSendArguments { Error = e, IPAddress = ep, Version = param.Version });
}
finally
{
if (param.Client != null)
param.Client.Close();
}
}
ev.Result = new AsyncSendArguments { Error = new Exception("Closing Listener Thread"), IPAddress = ep, Version = param.Version };
}
private void _ProgressChanged(object sender, ProgressChangedEventArgs e)
{
var arg = e.UserState as AsyncSendArguments;
try
{
WriteToDb(arg.Message, arg.Version, arg.IPAddress, arg.Operation, arg.Error);
}
catch (Exception ex)
{
WriteToDb(arg.Message, arg.Version, arg.IPAddress, DbOperation.Error, ex);
}
}
public static void WriteToDb(Byte[] message, GtpVersion version, IPEndPoint endpoint, DbOperation operation, Exception e = null)
{
lock (LockSql)
{
//SQL Operationen mit vorhandenen SqlConnection und SqlCommand.
...
...
}
}
Zuletzt bearbeitet: