开发者

WCF task scheduler, or timer like in OGame, Travian etc

开发者 https://www.devze.com 2023-03-03 09:41 出处:网络
I\'m looking for resources, or anyone who have writting scheduler in WCF. What I want to achive is basically what can you see in OGame, or Travian or doznes of other text browser based game.

I'm looking for resources, or anyone who have writting scheduler in WCF. What I want to achive is basically what can you see in OGame, or Travian or doznes of other text browser based game.

Player click and send task to server to make building for him, or unit or something else. From what I figured out I need to run some kind if scheduler on server that will gather all tasks, and will track them, until some perdiod of time will pass (2 mins, 10 mins, 3 days etc.), and after that period end service should call an action, like send data to database.

Well. I've been trying to make something very simply, that I can start from and ended with this:

    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();
    }

I have hardcoded most values, for testing.

InstanceContextMode is set for PerCall.

Anyway. This code is working. At least to some point. If we ignore zylion exceptions from Entity Framework, I can add tasks from multiple clients and they are added to db in order from newset to oldest (or shortest to longest ?).

The point is, user CANT track his tasks. When I change page I don't see how much time remaining till task done. This code essentialy do not provide time tracking because i got rid of it as it wasn't working anyway.

I guess I should store my task in some presitant data storage and everytime user check page newset state should be draw from that storage and send to him.

I'm not and expert but i think best option here is to store all data in Memory until task is done. Any relational database will be probably to slow, if I will have to constantly update records with newset state of task.

I know I should just synchronize client side timer with server and do not stream constatly time from server. But Big question is here how to get newset state of task pogress when user come back to page after 3 second or 3 hours ?

Any advices how to make it work as expected.

And btw. I'm using pollingduplex and Silverlight.


It sounds like you are using WCF to do something for which it wasn't designed (but I understand the need). I would suggest you look at Workflow Foundation (WF) as a possible solution to your problem. Here is a good explanation:

http://msdn.microsoft.com/library/dd851337.aspx

Here is also a good intro video:

http://channel9.msdn.com/Blogs/mwink/Introduction-to-Workflow-Services-building-WCF-Services-with-WF

Workflow can consume WCF services and it is designed to work over time. It holds data in state until something changes (regardless of time) without consuming excess resources. Also, it allows for persistance and parallel processes.

0

精彩评论

暂无评论...
验证码 换一张
取 消