Closed dylinmaust closed 4 years ago
Hi Dylan!
I made an attempt for a fix. I was not able to repro the issue (simply calling the controller twice), but I found a line of code that looks a bit funny, so I made an attempt at a fix.
Please give this branch a try and let me know if it works: https://github.com/amittleider/AutoFinance.Broker/pull/13/files .
As far as a recommended pattern to follow for polling, if It were me, I'd spin up a new thread using some code like the following, and put a sleep in there and whatever logic you want. However, maybe you want to use event based functions? In that case, you can use the TwsEventHandler in the lib and attach any function you want to any event. I put a small example of that below as well.
this.readerThread = new Thread(
() =>
{
while (true)
{
this.signal.waitForSignal();
reader.processMsgs();
}
})
{ IsBackground = true };
this.readerThread.Start();
Event handler example
openOrderEndEventHandler = (sender, args) =>
{
// Your logic here
};
this.twsCallbackHandler.OpenOrderEvent += openOrderEventHandler;
Thanks for the quick response.
I created a console app but am unable reproduce the issue while referencing the current nuget package:
Program.cs:
static async Task Main(string[] args)
{
var twsObjectFactory = new TwsObjectFactory();
var connectionController = new TwsConnectionController(twsObjectFactory.ClientSocket, twsObjectFactory.TwsCallbackHandler, "127.0.0.1", 7462, 1);
var openOrdersController = new TwsOpenOrdersController(twsObjectFactory.ClientSocket, twsObjectFactory.TwsCallbackHandler);
await connectionController.EnsureConnectedAsync();
var openOrders = await openOrdersController.RequestOpenOrders();
var secondOrders = await openOrdersController.RequestOpenOrders();
var thirdOrders = await openOrdersController.RequestOpenOrders();
}
csproj:
<PackageReference Include="AutoFinance.Broker" Version="1.0.412" />
I've since pulled down the for_dylan
branch and tried referencing it directly in a dotnet core controller endpoint:
public async Task<IActionResult> TestOrders()
{
var twsObjectFactory = new TwsObjectFactory();
var connectionController = new TwsConnectionController(twsObjectFactory.ClientSocket, twsObjectFactory.TwsCallbackHandler, "127.0.0.1", 7462, 1);
var openOrdersController = new TwsOpenOrdersController(twsObjectFactory.ClientSocket, twsObjectFactory.TwsCallbackHandler);
await connectionController.EnsureConnectedAsync();
var openOrders = await openOrdersController.RequestOpenOrders();
return Ok();
}
Again, it exhibits the behavior described above - the first execution succeeds but subsequent calls to that endpoint result in a TaskCanceledException
! I'm curious if this has something to do with the context in which the TWS code is running? It seems to be fine in a console application, but fails in a web application?
Hi Dylin, apologies for misspelling your name before.
I don't think the problem is the context, but instead, it's the time between calls. In your web application, there is more than 5 seconds between calls (the amount of time to cancel the task), but in your console application, you call twice within 5 seconds, so the task is not cancelled.
I was able to repro the issue by putting the 5 second sleep in the test, so I feel pretty confident that the TrySetCancelled
fix works. Is it possible that you were still using the old version of the code?
I have fixed the bug and published a new nuget package, version 1.0.435
, can you try it? If it's still not working, please provide me with a code sample to repro.
No problem!
I've confirmed that the latest package working as expected. I think the issue was related to debugging and the 5 second timeout, potentially my Autofac configuration as well as it was potentially recreating TwsObjectFactory
and all the Controller services instead of reusing single instances. I've configured the background service to run with some logging and all services have been successful. Thank you for your help.
As a heads up, I will likely submit PRs for TWS APIs that are not covered under this library that are required for my app - features like:
reqGlobalCancel()
to cancel all ordersreqAutoOpenOrders()
to open all orders (even those submitted in another client) and assign order IDsAnd potentially others. Please let me know if you foresee any issues or have any guidance. It seems like they'd be pretty straightforward to implement.
Thanks again for your help!
You're PRs are welcome, I'd be happy to read them.
Thank you for your work on this great library!
Is there a recommended pattern to follow when polling for events? I've configured a dotnet core Background Service to poll TWS - the first call to something like
await openOrdersController.RequestOpenOrders();
successfully returns data. But subsequent calls throwTaskCanceledException
every time.I've tried both registering
TwsObjectFactory
andTwsConnectionController
in Autofac to inject them in a class manually constructing them up for each poll iteration. Both results in this behavior.https://github.com/amittleider/AutoFinance.Broker/blob/37e230cc5f9da40c4868874f7505c07a143aa31b/AutoFinance.Broker/InteractiveBrokers/Controllers/TwsOpenOrdersController.cs#L66