我创建了一个类,该类具有由不同线程(在类外)调用的方法。在调用该方法之前,线程通过更新类中的属性字典来更新它们自己的参数集。我通过从字典中选择适当的项目来参数化该方法。
该方法中包含各种变量并执行各种计算。如果计算返回某个值,则该方法将控制权传递给几个外部 API 之一,等待 API 传回一个值,将该值写入数据库,然后退出。
我希望该方法的每个调用都是完全独立的——即线程 A 不应干扰线程 B 中变量的值,反之亦然。我最初的阅读表明这不是用于 C# 中的线程化的模型,而是方法中的每个变量都可以由任何线程访问和更新 - 即 Datarace(?可能在这里使用了不正确的术语)。锁定对我来说并不理想,因为每个线程的执行时间很重要。(如果我锁定,我知道线程将被顺序执行,因为它们引用相同的方法/变量)。
我想我实现了我在 python 中使用线程池的行为,尽管这可能只是我在有限的使用期间很幸运!
如上所述,是否可以在 C# 中让方法调用/线程完全相互独立?如果是这样,请您指出我应该寻找的方向吗?
非常感谢。
更新:根据要求,这是我正在尝试做的代码的摘录。我已经删除了大部分与计算相关的代码,只留下了注释以及不同的类如何调用线程等。
//Websockets sharp on-message event
//Within namespace1.class1
ws.OnMessage += (sender, e) =>
{ //write a whole lot of pricing data to a dictionary ("price dictionary") and identify whether we should re-evealuate our pricing conditions
if (blnReevaluatePricingConditions)
{
nsStrategy.csStrategy objPriceCheck = new nsStrategy.csStrategy();
objPriceCheck.EvaluatePricingConditions(strExchange, strInstrument);
}
}
// within nsStrategy.csStrategy
public void EvaluatePricingConditions(string strExchange = "", string strInstrument = "")
{ //evaluate the pricing conditions (stored in a dictionary ("conditions dictionary")) against the price dictionary
//If conditions evaluate to trade = true, create a list of >1 sets of trade parameters to execute using REST API
nsREST.csREST myRESTObject = new nsREST.csREST();
nsREST.MarketOrder[] MOs = new nsREST.MarketOrder[n]; //n>1 - MOs stands for Market Orders
//Populate list
//...
//Execute by passing the list to a method in the csREST class object just created
myRESTObject.MarketOrder(MOs);
//Wait for completion of REST API calls
//Update db with parameters from MOs list
//End method
}
//within nsRest.csRest
public void MarketOrder(MarketOrder[] mktOs)
{
//Create a list of exchange methods (i.e. parameters for the exchange APIs)
ExchangeMethod[] lstExchangeMethods = new ExchangeMethod[mktOs.GetUpperBound(0)+1];
//Create a list of objects populted from the JSON the exchanges return
RestReturns[] rstReturn = new RestReturns[mktOs.GetUpperBound(0)+1];
//Populate the lstExchangeMEthods...and call a method passing it the list
rstReturn = threadedExchangeMethod(lstExchangeMethods);
}
public RestReturns[] threadedExchangeMethod(ExchangeMethod[] lstExchangeMethods)
{ //Executes the ExchangeMethods passed to it simultaneously, then waits for response from each.
List<Thread> lstThreads = new List<Thread>();
RESTGlobalVars.ExchangeMethodList = lstExchangeMethods;
//Now add a new thread to the list and start it with the parameters below
for (int i = 0; i <= lstExchangeMethods.GetUpperBound(0); i++)
{
lstThreads.Add(new Thread(ThreadedExchangeMethodExecution));
Thread.Sleep(5); //allow a tiny bit of time for the first thread to update to completed status
lstThreads[lstThreads.Count() - 1].Start();
}
}
private void ThreadedExchangeMethodExecution()
{
//Loop through the class-level list of exchangemethod parameters, set blnCompleted to true so it's not picked again by the next thread and call the ExchangeMethods method with the parameters
for (int i = 0; i <= RESTGlobalVars.ExchangeMethodList.GetUpperBound(0); i++)
{
if (RESTGlobalVars.ExchangeMethodList[i].Completed == false)
{
RESTGlobalVars.ExchangeMethodList[i].Completed = true;
RestReturns rstResponse = ExchangeMethods(RESTGlobalVars.ExchangeMethodList[i].Exchange, RESTGlobalVars.ExchangeMethodList[i].Method, RESTGlobalVars.ExchangeMethodList[i].Parameters);
rstResponse.Exchange = RESTGlobalVars.ExchangeMethodList[i].Exchange;
RESTGlobalVars.ExchangeMethodList[i].Response = rstResponse;
}
}
}
public class ExchangeMethod
{
public string Exchange { get; set; }
public string Method { get; set; }
public string Parameters { get; set; }
public Boolean Completed { get; set; }
public RestReturns Response { get; set; }
}
public class MarketOrder
{
public string StrategyName { get; set; }
public string Exchange { get; set; }
public string Instrument { get; set; }
public string BuyOrSell { get; set; }
public double VolumeInUSD { get; set; }
}
public static class RESTGlobalVars
{
public static ExchangeMethod[] ExchangeMethodList { get; set; }
public static Dictionary<string, RateLimits> dtRateWait = new Dictionary<string, RateLimits>();
}
在工作流程方面,我收到一条 websocketssharp 消息(我相信这是一个后台线程)。这可能来自几个 websocket 提要之一,每个提要都包含在自己的命名空间和类中,并且每个提要都以相同的逻辑继续。我评估消息,将其中的价格放入字典中,然后调用一个方法来评估价格以确定我们是否应该交易。然后,此方法进行一些计算并(如果适用)创建交易参数列表,然后调用名为 MarketOrder 的方法,将参数列表传递给它。市价单参数被转换为一个类似的(稍微冗余的)交换方法参数列表,每个参数都有一个设置为 false 的“已完成”参数,这些参数被写入一个类级别(“全局”)列表。然后我们为列表中的每个项目创建一个新线程。每个线程检查全局列表,并从列表中拉出第一个未完成的项目。它将完成的参数设置为 true,然后执行 API 调用。
感谢迄今为止做出回应的人-我正在阅读您的建议...