我正在寻找资源,或者在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();
}
我已经硬编码了大多数值,用于测试。
为PerCall设置了InstanceContextMode。
反正。这段代码正在运行。至少在某种程度上。如果我们忽略来自Entity Framework的zylion异常,我可以从多个客户端添加任务,并按照从newset到最旧(或从最短到最长?)的顺序将它们添加到db。
关键是,用户CANT跟踪他的任务。当我改变页面时,我看不到任务完成剩余的时间。这段代码本质上不提供时间跟踪,因为我摆脱它,因为它无论如何都没有。
我想我应该将我的任务存储在一些预先存储的数据存储中,并且每次用户检查页面都应该从该存储中抽取新的状态并发送给他。
我不是专家,但我认为这里的最佳选择是将所有数据存储在内存中,直到任务完成。 如果我必须不断更新具有newset任务状态的记录,任何关系数据库都可能会变慢。
我知道我应该只将客户端计时器与服务器同步,并且不要从服务器传输持续时间。但是,当用户在3秒或3小时后回到页面时,如何获得新的任务进度状态这里有一个很大的问题?
任何建议如何使其按预期工作。
顺便说一下。我正在使用pollingduplex和Silverlight。
答案 0 :(得分:1)
听起来你正在使用WCF来做一些它没有设计的东西(但我明白需要)。我建议您查看Workflow Foundation(WF)作为您问题的可能解决方案。这是一个很好的解释:
http://msdn.microsoft.com/library/dd851337.aspx
这也是一个很好的介绍视频:
http://channel9.msdn.com/Blogs/mwink/Introduction-to-Workflow-Services-building-WCF-Services-with-WF
工作流可以使用WCF服务,它可以随着时间的推移而运行。它保持状态数据直到某些变化(无论时间如何)而不消耗过多的资源。此外,它允许持久性和并行过程。