我有一个SignalR项目,我使用System.Timers.Timer
类每秒向网页发送通知。
在我的网页中,我有一个文本输入和两个按钮,一个用于使用文本输入中的过滤器值开始接收更新,另一个用于停止计时器。
问题是如果在文本输入中输入了一个值并且我单击了开始按钮,我开始接收更新,这很好,但是当我在文本输入中输入新值并再次单击开始按钮时开始接收新值和旧值的更新。
如果我点击停止按钮,定时器将不会停止。
我尝试了timer.Stop(), timer.Close(), timer.Dispose(), timer.Enabled = false
,但没有一个停止计时器。
我还尝试设置timer.AutoReset = false
,然后在经过事件结束时手动启动计时器,如果布尔变量设置为true,但布尔变量从未更改过。
我的猜测是,每次单击开始按钮,它都会在另一个线程上启动,该线程看不到主线程中发生的任何更改。
这是集线器代码:
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();
});
});
答案 0 :(得分:0)
使用System.Threading.Timer并使用事件Tick而不是Elapsed。 现在你的计时器应该停在stock.Stop();
但你可以像stock.Interval = Int32.MaxValue;
那样做一个肮脏的解决方法答案 1 :(得分:0)
每次需要处理Hub操作时,SignalR都会创建一个Hub类的新实例,例如客户端连接,断开连接或对服务器进行方法调用时。由于Hub类的实例是瞬态的,因此您无法使用它们来保持从一个方法调用到下一个方法调用的状态。每次服务器从客户端接收方法调用时,Hub类的新实例都会处理该消息。要通过多个连接和方法调用来维护状态,请使用其他方法,例如数据库或Hub类上的静态变量,或使用不从Hub派生的其他类
简而言之,您在每次到达集线器的请求时都会创建一个新的时间实例,因此无论您做什么都不会影响您所拥有的内容完成在先前请求中创建的实例。您必须为每个会话或每个应用程序使用一个实例(取决于您的要求),并相应地存储它。