Я ищу ресурсы или тех, у кого есть планировщик записи в WCF.
Чего я хочу достичь, так это того, что вы можете увидеть в OGame, Travian или десятках других текстовых браузерных игр.
Игрок кликает и отправляет задачу на сервер, чтобы построить для него здание, или юнит, или что-то еще.
Из того, что я понял, мне нужно запустить какой-нибудь планировщик на сервере, который соберет все задачи и будет отслеживать их, пока не пройдет какое-то время (2 минуты, 10 минут, 3 дня и т. Д.) И после этого периода. конечная служба должна вызывать действие, например отправлять данные в базу данных.
Хорошо. Я пытался сделать что-то очень просто, с чего я мог бы начать и закончить так:
public class BuildingScheduler
{
public int TaskID { get; set; }
public string UserName { get; set; }
public DateTime TaskEnd { get; set; }
public string BuildingName { get; set; }
public bool TaskDone { get; set; }
public DateTime RemainingTime { get; set; }
TestDBModelContainer _ctx;
TestData _testData;
public IDuplexClient Client { get; set; }
public BuildingScheduler()
{
TaskDone = false;
}
public void MakeBuilding()
{
while (DateTime.Now <= TaskEnd)
{
//Client.DisplayMessage(DateTime.Now.ToString());
RemainingTime = DateTime.Now;
}
_testData = new TestData { DataName = BuildingName, Created = DateTime.Now };
_ctx = new TestDBModelContainer();
_ctx.TestDataSet.AddObject(_testData);
_ctx.SaveChanges();
TaskDone = true;
//Client.DisplayMessage("Building completed!");
}
}
static List<UserChannel> _userChannels = new List<UserChannel>();
static List<BuildingScheduler> _buildingSchedules = new List<BuildingScheduler>();
List<BuildingScheduler> _buildingSchedulesToRemove = new List<BuildingScheduler>();
[OperationContract]
public void DoWork()
{
IDuplexClient client = OperationContext.Current.GetCallbackChannel<IDuplexClient>();
UserChannel userChannel = new UserChannel { Client = client, ClientName = "TestClient" };
string clientName = (from p in _userChannels
where p.ClientName == "TestClient"
select p.ClientName).FirstOrDefault();
lock (((ICollection)_userChannels).SyncRoot)
{
if (clientName == null)
{
_userChannels.Add(userChannel);
}
}
CheckBuilding();
}
private void CheckBuilding()
{
BuildingScheduler bs = (from p in _buildingSchedules
where p.UserName == "TestClient"
select p).FirstOrDefault();
IDuplexClient client = (from p in _userChannels
where p.ClientName == "TestClient"
select p.Client).FirstOrDefault();
if (bs != null)
{
client.DisplayMessage(bs.RemainingTime);
}
}
private void StartBuilding()
{
foreach (BuildingScheduler bs in _buildingSchedules)
{
if (bs.TaskDone == false)
{
bs.MakeBuilding();
}
else if (bs.TaskDone == true)
{
_buildingSchedulesToRemove.Add(bs);
}
}
for(int i = 0; i <= _buildingSchedulesToRemove.Count; i++)
{
BuildingScheduler bs = _buildingSchedulesToRemove.Where(p => p.TaskDone == true).Select(x => x).FirstOrDefault();
_buildingSchedules.Remove(bs);
_buildingSchedulesToRemove.Remove(bs);
}
CheckBuilding();
}
[OperationContract]
public void MakeBuilding(string name)
{
BuildingScheduler _buildng = new BuildingScheduler();
//_buildng.Client = client;
_buildng.TaskID = 1;
_buildng.UserName = "TestClient";
_buildng.TaskEnd = DateTime.Now.AddSeconds(50);
_buildng.BuildingName = name;
_buildingSchedules.Add(_buildng);
StartBuilding();
}
У меня жестко задано большинство значений для тестирования.
InstanceContextMode установлен для PerCall.
Так или иначе. Этот код работает. По крайней мере, в какой-то момент. Если мы игнорируем исключения zylion из Entity Framework, я могу добавить задачи от нескольких клиентов, и они будут добавлены в БД в порядке от newset до самого старого (или от самого короткого до самого длинного?).
Дело в том, что пользователь CANT может отслеживать свои задачи. Когда я меняю страницу, я не вижу, сколько времени осталось до выполнения задачи. Этот код по сути не обеспечивает отслеживание времени, потому что я избавился от него, так как он все равно не работал.
Полагаю, я должен хранить свою задачу в каком-то главном хранилище данных, и каждый раз, когда пользователь проверяет состояние новой страницы, проверяемое из этого хранилища, следует отправлять ему.
Я не эксперт, но я думаю, что лучший вариант здесь - хранить все данные в памяти, пока задача не будет выполнена.
Любая реляционная база данных, вероятно, будет работать медленно, если мне придется постоянно обновлять записи с заданным состоянием задачи.
Я знаю, что должен просто синхронизировать таймер на стороне клиента с сервером и не передавать потоковое время с сервера. Но здесь возникает большой вопрос, как получить новое состояние задачи, когда пользователь возвращается на страницу через 3 секунды или 3 часа?
Любые советы, как заставить его работать как положено.
И, кстати. Я использую pollingduplex и Silverlight.