Hallo zusammen
Aus meinem MainViewModel rufe ich die folgende Methode auf:
private void TextBoxSymbolExecute(object obj)
{
Option option1 = Option1;
TWSInterface.DataForOptionsRow(Symbol, ref option1);
MessageBox.Show("");
option1.Stk = option1.StkList[0];
}
Nun ist es so, dass option1.Stk nur einen Wert erhält, wenn die darüberliegende Zeile "Messagebox.Show(""); besteht. Ansonsten erhalte ich eine SystemOutOfRange-Exception, weil option1.Stk null ist, was es nicht sein soll.
Kann mir jemand helfen wie ich das (Thread)-Problem umgehen/lösen kann?
Nachfolgend noch den Code der TWSInterface-Klasse:
public class TWSInterface : EWrapperImpl
{
//Eigenschaften
int contractUnderlyingID;
ObservableCollection<float> stkList;
//Konstruktoren
public TWSInterface()
{
stkList = new ObservableCollection<float>();
}
//Methoden
//Call to TWS-API
public void Connect()
{
ClientSocket.eConnect("", 7496, 0);
var reader = new EReader(ClientSocket, Signal);
reader.Start();
new Thread(() =>
{
while (ClientSocket.IsConnected())
{
Signal.waitForSignal();
reader.processMsgs();
}
})
{ IsBackground = true }.Start();
while (NextOrderId <= 0) { }
}
public void DataForOptionsRow(string symbol, ref Option zo)
{
ClientSocket.reqContractDetails(100, contractUnderlying);
zo.StkList = stkList;
}
//Recall from TWS-API
public override void contractDetails(int reqId, ContractDetails contractDetails)
{
printContractMsg(contractDetails.Contract);
}
public override void printContractMsg(Contract contract)
{
contractUnderlyingID = contract.ConId;
ClientSocket.reqSecDefOptParams(0, contract.Symbol, "", "STK", contractUnderlyingID);
}
public override void securityDefinitionOptionParameter(int reqId, string exchange, int underlyingConId, string tradingClass, string multiplier, HashSet<string> expirations, HashSet<double> strikes)
{
//Sicherstellung, dass der Zugriff auf die ObservableCollection auf dem UI-Thread erfolgt
Application.Current.Dispatcher.BeginInvoke(() =>
{
stkList.Clear();
foreach (double strike in strikes)
{
float strikeFloat = (float)strike;
stkList.Add(strikeFloat);
}
});
}
}
Hallo,
so wie ich deinen Code verstehe, hast du ein zeitliches Problem (was durch die MessageBox
kaschiert wird).
Ohne den MessageBox
-Aufruf ist die Liste option1.StkList
leer (so daß der Zugriff auf Index 0
die Exception auslöst). Im Konstruktor von TWSInterface
erzeugst du diese leere Liste, gefüllt wird sie aber nur in securityDefinitionOptionParameter
(welche anscheinend in DataForOptionsRow
durch ClientSocket.reqContractDetails(...)
asynchron aufgerufen wird).
Du mußt (logisch / zeitlich) sicherstellen, daß die Daten erst komplett eingelesen sind, bevor die weitere Abarbeitung erfolgt. Am besten beschäftigst du dich mal mit der asynchronen Programmierung (Task<T>
/async
/ await
).
PS: Die Schleife while (NextOrderId <= 0) { }
, um auf das Setzen einer Variablen (aus einem anderen Thread) zu warten, ist ein No-Go (so erzeugst du 100% Kernlast)!
Und auch der Dispatcher
-Aufruf ist m.E. dort unnötig (bzw. an der falschen Stelle): eine ObservableCollection<T>
per se benötigt dies nicht, nur wenn sie an ein UI-Element gebunden ist.