无法使用 SignalR 停止计时器
Can't stop timer with SignalR
我有一个 SignalR 项目,我在其中使用 System.Timers.Timer
class 每秒向网页发送通知。
在我的网页中,我有一个文本输入和两个按钮,一个用于使用文本输入中的过滤器值开始接收更新,另一个用于停止计时器。
问题是,如果在文本输入中输入一个值并单击开始按钮,我会开始接收更新,这很好,但是当我在文本输入中输入一个新值并单击开始按钮时我再次开始接收新值和旧值的更新。
如果我点击停止按钮,计时器不会停止。
我尝试了 timer.Stop(), timer.Close(), timer.Dispose(), timer.Enabled = false
,但 none 停止了计时器。
我还尝试设置 timer.AutoReset = false
,如果布尔变量设置为真,则在经过的事件结束时手动启动计时器,但布尔变量从未改变。
我的猜测是,每次单击开始按钮时,它都会在一个不同的线程上启动,该线程看不到主线程中发生的任何变化。
这是中心代码:
public class HubClass : Hub
{
System.Timers.Timer stock = new System.Timers.Timer();
int id = 1;
SqlCommand dataRetriver = new SqlCommand();
bool getNextFeed = true;
public void Start(string user)
{
USERID = user;
id = 1;
dataRetriver.Connection = con;
dataRetriver.CommandText = "GetData";
dataRetriver.CommandType = CommandType.StoredProcedure;
dataRetriver.Connection = con;
param.ParameterName = "userId";
param.Value = USERID;
param2.ParameterName = "@id";
param2.Value = id;
dataRetriver.Parameters.Clear();
dataRetriver.Parameters.Add(param);
dataRetriver.Parameters.Add(param2);
stock.Elapsed -= new ElapsedEventHandler(stock_Elapsed);
stock.Elapsed += new ElapsedEventHandler(stock_Elapsed);
stock.Interval = 1000;
stock.AutoReset = false;
stock.Start();
}
public void Stop()
{
//stock.Stop();
getNextFeed = false;
//stock.Start();
}
void stock_Elapsed(object sender, ElapsedEventArgs e)
{
var context = GlobalHost.ConnectionManager.GetHubContext<HubClass>();
if (con.State == ConnectionState.Closed)
con.Open();
dataRetriver.Parameters.Clear();
param2.Value = id;
dataRetriver.Parameters.Add(param);
dataRetriver.Parameters.Add(param2);
SqlDataReader reader = dataRetriver.ExecuteReader();
DataTable allData = new DataTable();
allData.Load(reader);
string jsonString = JsonConvert.SerializeObject(allData);
context.Clients.All.broadCastMessage(jsonString);
id = id + 1;
con.Close();
if (getNextFeed)
{
stock.Start();
}
}
}
这是我的 javascript 代码:
$(function () {
var chat = $.connection.hubClass;
chat.client.broadCastMessage = function (msg) {
//update html table data
};
$.connection.hub.logging = true;
$.connection.hub.start().done(function () {
console.log($.connection.hub.transport.name);
});
$("#btn_filter").click(function () {
chat.server.start($("#txt_id").val());
});
$("#btn_stop").click(function () {
chat.server.stop();
});
});
脏或正常
使用 System.Threading.Timer 并使用事件 Tick 而不是 Elapsed。
现在你的计时器应该停止在 stock.Stop();
但是你可以做一个肮脏的解决方法,比如 stock.Interval = Int32.MaxValue;
SignalR creates a new instance of your Hub class each time it needs to handle a Hub operation such as when a client connects, disconnects, or makes a method call to the server.
Because instances of the Hub class are transient, you can't use them to maintain state from one method call to the next. Each time the server receives a method call from a client, a new instance of your Hub class processes the message. To maintain state through multiple connections and method calls, use some other method such as a database, or a static variable on the Hub class, or a different class that does not derive from Hub
简而言之,您正在为到达您的中心的每个请求创建一个 new 时间实例,因此无论您对它做什么都不会影响您所做的事情到在先前请求中创建的实例。您必须为每个会话或每个应用程序使用一个实例(取决于您的要求),并相应地存储它。
我有一个 SignalR 项目,我在其中使用 System.Timers.Timer
class 每秒向网页发送通知。
在我的网页中,我有一个文本输入和两个按钮,一个用于使用文本输入中的过滤器值开始接收更新,另一个用于停止计时器。
问题是,如果在文本输入中输入一个值并单击开始按钮,我会开始接收更新,这很好,但是当我在文本输入中输入一个新值并单击开始按钮时我再次开始接收新值和旧值的更新。
如果我点击停止按钮,计时器不会停止。
我尝试了 timer.Stop(), timer.Close(), timer.Dispose(), timer.Enabled = false
,但 none 停止了计时器。
我还尝试设置 timer.AutoReset = false
,如果布尔变量设置为真,则在经过的事件结束时手动启动计时器,但布尔变量从未改变。
我的猜测是,每次单击开始按钮时,它都会在一个不同的线程上启动,该线程看不到主线程中发生的任何变化。
这是中心代码:
public class HubClass : Hub
{
System.Timers.Timer stock = new System.Timers.Timer();
int id = 1;
SqlCommand dataRetriver = new SqlCommand();
bool getNextFeed = true;
public void Start(string user)
{
USERID = user;
id = 1;
dataRetriver.Connection = con;
dataRetriver.CommandText = "GetData";
dataRetriver.CommandType = CommandType.StoredProcedure;
dataRetriver.Connection = con;
param.ParameterName = "userId";
param.Value = USERID;
param2.ParameterName = "@id";
param2.Value = id;
dataRetriver.Parameters.Clear();
dataRetriver.Parameters.Add(param);
dataRetriver.Parameters.Add(param2);
stock.Elapsed -= new ElapsedEventHandler(stock_Elapsed);
stock.Elapsed += new ElapsedEventHandler(stock_Elapsed);
stock.Interval = 1000;
stock.AutoReset = false;
stock.Start();
}
public void Stop()
{
//stock.Stop();
getNextFeed = false;
//stock.Start();
}
void stock_Elapsed(object sender, ElapsedEventArgs e)
{
var context = GlobalHost.ConnectionManager.GetHubContext<HubClass>();
if (con.State == ConnectionState.Closed)
con.Open();
dataRetriver.Parameters.Clear();
param2.Value = id;
dataRetriver.Parameters.Add(param);
dataRetriver.Parameters.Add(param2);
SqlDataReader reader = dataRetriver.ExecuteReader();
DataTable allData = new DataTable();
allData.Load(reader);
string jsonString = JsonConvert.SerializeObject(allData);
context.Clients.All.broadCastMessage(jsonString);
id = id + 1;
con.Close();
if (getNextFeed)
{
stock.Start();
}
}
}
这是我的 javascript 代码:
$(function () {
var chat = $.connection.hubClass;
chat.client.broadCastMessage = function (msg) {
//update html table data
};
$.connection.hub.logging = true;
$.connection.hub.start().done(function () {
console.log($.connection.hub.transport.name);
});
$("#btn_filter").click(function () {
chat.server.start($("#txt_id").val());
});
$("#btn_stop").click(function () {
chat.server.stop();
});
});
脏或正常
使用 System.Threading.Timer 并使用事件 Tick 而不是 Elapsed。 现在你的计时器应该停止在 stock.Stop();
但是你可以做一个肮脏的解决方法,比如 stock.Interval = Int32.MaxValue;
SignalR creates a new instance of your Hub class each time it needs to handle a Hub operation such as when a client connects, disconnects, or makes a method call to the server.
Because instances of the Hub class are transient, you can't use them to maintain state from one method call to the next. Each time the server receives a method call from a client, a new instance of your Hub class processes the message. To maintain state through multiple connections and method calls, use some other method such as a database, or a static variable on the Hub class, or a different class that does not derive from Hub
简而言之,您正在为到达您的中心的每个请求创建一个 new 时间实例,因此无论您对它做什么都不会影响您所做的事情到在先前请求中创建的实例。您必须为每个会话或每个应用程序使用一个实例(取决于您的要求),并相应地存储它。