我正在开发一个通过SignalR客户端执行SQL过程的Winforms应用程序。我对使用SignalR比较陌生,我仍然围绕着它。
我首先运行我的连接方法来建立与SignalR服务的连接。我有两个地址配置好,当我puslish但DEV配置导致我在本地托管的SignalR服务。
连接SignalR(ConnectHub)
private async Task ConnectHub()
{
string hubAddress = "";
#if DEBUG
HubAddress = ConfigurationManager.AppSettings["HubAddress_DEV"];
#else
HubAddress = ConfigurationManager.AppSettings["HubAddress_PROD"];
#endif
if (string.IsNullOrEmpty(hubAddress))
{
MessageBox.Show("Hub Address is missing from configuration.");
}
ConnectionHandler.Client = new HubClient(hubAddress, "MyHub");
ConnectionHandler.Client.MyAlert += ConnectionHandler.ClientOnMyAlert;
ConnectionHandler.Client.ServerErrorEvent += ConnectionHandler.ClientOnServerErrorEvent;
await ConnectionHandler.Client.Connect(new List<string>() {
VehicleInfo.ThisVehicle.WarehouseCode,
VehicleInfo.ThisVehicle.VehicleName
});
}
我的客户端全局存储在我的ConnectionHandler类中,我的事件处理程序也保存在该类中。 (我在这些方面有断点,因为我还没有实现它们)
ConnectionHandler类
public static class ConnectionHandler
{
public static HubClient Client { get; set; }
public static void ClientOnServerErrorEvent(string error)
{
throw new NotImplementedException(); //Currently not implemented
}
public static async Task ClientOnMyAlert(EnumMyAlertType alerttype, string message, Exception exception)
{
await Task.Yield(); //Currently not implemented
}
}
当我调用代码调用SignalR客户端中的过程时,它会向我返回一个DataTable,这是预期的结果。致电SignalR
await ConnectHub();
DataTable dt = await ConnectionHandler.Client.Connection.InvokeCoreAsync<DataTable>(
"FetchStatuses",
new object[0]); //This call works as intended and returns a populated DataTable
StatusInfo = new CStatuses();
上面的所有代码目前都是在主窗体上完成的,但是我想把这个调用信号转移到一个构造函数中来尝试整理。
当我尝试将此调用移动到另一个方法时问题出现,程序挂起,因为我认为它没有从SignalR收到返回值,我在它下面放置了一个断点并且没有到达。 TryCatch没有显示任何内容,因为它在“Try”中挂起,没有例外。
从构造函数调用
public CStatuses()
{
Statuses = new List<CStatus>();
var dataTable = ConnectionHandler.Client.Connection.InvokeCoreAsync<DataTable>("FetchStatuses",
new object[0])
.Result; //My program hangs on this line and proceeds no further
当我从表单中获取客户端的值并且当我的团队的其他成员尝试做同样的事情他们也可以通过不同的方法调用SignalR时,我不知道为什么会这样做。
有没有人对如何使这项工作有任何想法?
我意识到这已经很长了但如果我能详细说明,请告诉我
解决的固定代码:我已经将我的CStatuses构造函数中的代码移动到同一个类中的新异步方法中,并在初始化后调用它。这消除了对.Result
的需求,似乎为我解决了这个问题。
public async Task PopulateStatuses()
{
var dataTable = await ConnectionHandler.Client.Connection.InvokeCoreAsync<DataTable>("FetchStatuses",
new object[0]);
Statuses = new List<CStatus>();
foreach (DataRow row in dataTable.Rows)
{
var status = new CStatus
{
StatusId = Common.Utility.GetInt16Value(row["StatusID"]),
StatusCode = Common.Utility.GetStringValue(row["StatusCode"]),
Description = Common.Utility.GetStringValue(row["Description"])
};
Statuses.Add(status);
}
}
您正在使用.Result调用遇到死锁,我建议在CStatuses类中创建一个异步方法,并在初始化CStatuses类之后调用websocket以获取数据。