在C# / .NET中访问相同的对象类

huangapple go评论60阅读模式
英文:

Accessing the same object class in C# / .NET

问题

我有一个使用C# Winforms制作的桌面应用程序,还有一个使用.NET的API,想法是让许多人可以访问桌面应用程序并拥有许多独特创建的类(窗体),但使用相同的API类(我们称其为Manager)。

因此,如果一个用户在Manager类中更新了对象A,那么每个访问该类的其他用户都应该得到更新,而不使用数据库。我猜你需要以某种方式使用内存,但我不确定如何做。

我脑海中想到的另一个解决方案是,在启动API时创建Manager类,然后在需要使用它时将它作为变量传递,但由于它是C#窗体,我正在寻找更好的解决方案。

代码 - Manager类:

private static RoundManager instance;

public static RoundManager GetInstance()
{
    if (instance == null)
    {
        RoundHandler _handlers = new RoundHandler();
        instance = new RoundManager(_handlers);
    }

    return instance;
}

应用程序:

public Ranked(User user1, User user2, Game game, Round round, RoundManager _manager)
{
    InitializeComponent();
    this._manager = RoundManager.GetInstance();
}

问题出在,当我在第一台机器上运行应用程序时,实例为空,因此if语句为true,创建了Manager,但是当我在另一台机器上运行它(在所有这些之后,即Manager类被创建之后),它会做相同的事情并读取实例为空。

【注意】由于上下文限制,我提供了代码的翻译,但是代码的功能和问题可能需要更多的详细信息才能完全理解和解决。如果需要更多帮助,请提供更多上下文信息。

英文:

I have a desktop application made with C# Winforms and an API with .NET, the idea is that many people can access the desktop application and have many unique created classes (forms) but use THE SAME API class (let's call it Manager).

So, if one user updates object A in that Manager class, it should be updated for every other user who accesses that class, without using a database. I guess you have to use the memory in some sort of a way, but I am not sure how.

Another solution I got in my head was when starting the API, to create the Manager class and just pass it as a variable whenever it has to be used, but since it is a C# forms, I am searching for a better solution?

Code - the Manager class:

    private static RoundManager instance;

    public static RoundManager GetInstance()
    {
        if (instance == null)
        {
            RoundHandler _handlers = new RoundHandler();
            instance = new RoundManager(_handlers);
        }

        return instance;
    }

The app

public Ranked(User user1, User user2, Game game, Round round, RoundManager _manager)
{
    InitializeComponent();
    this._manager = RoundManager.GetInstance();
}

What happens is when I run the application on the first machine, the instance is empty so the if statement is true and the Manager is created, however, when I run it on the other machine (after all this, so after the manager class was created), it would do the same thing and read that the instance is null.

答案1

得分: 2

听起来你正在尝试创建一个模型,其中多个副本的桌面应用程序在不同的计算机上运行,并共享某种状态或调用共享的API的能力。这是一个相当复杂的问题,我认为你可能不会找到很多精确解决这个问题的示例代码。我建议你搜索"分布式缓存"、"分布式事务"、"消息队列"和"事件溯源"来了解更多信息。

如果所有应用程序都在同一台计算机上运行,那么你可以使用内存映射文件,就像另一个答案中描述的那样。但是,听起来你需要跨计算机访问信息,让每个人都能访问共享服务。这是一个非常复杂的架构(特别是没有中央服务器的情况下),但是有方法可以实现它。这些架构通常用于协调服务器之间的操作。

如果可能的话,将API逻辑移入一个在单个持久性计算机上运行的Web服务将比以下任何操作都要容易得多。

要在不同计算机上运行的桌面应用程序之间管理状态,你需要执行以下三种操作之一:

  1. 配置一个桌面应用程序,使其成为维护状态并为其他桌面应用程序提供API请求的中央服务。也就是说,类似于在服务器上运行的Web服务,但在你的应用程序内部。你需要一种方法来让所有应用程序的副本都能够访问它。如果这些应用程序还将在不同的网络上运行,那么这个服务需要通过互联网访问。你还必须考虑如果另一台机器需要它的时候这台机器没有运行会发生什么情况。

  2. 节点群集,其中的一个节点被选为服务器。这通过使所有应用程序都能够成为服务器,并在任何特定时间决定哪一个应用程序成为服务器来解决了需要一台机器一直运行的问题。然后,它们都会获得状态的副本并且可以在选定的服务器消失时接管。

  3. 分布式缓存 - 如果所有状态更改可以在桌面应用程序中本地排序,然后定期发送到其他应用程序,你可以通过实施分布式缓存来使集群操作更加高效和可靠,该缓存将在所有应用程序之间同步状态。然后,你在应用程序所在的机器上本地更改事物,让分布式缓存复制信息到其他应用程序中。

要了解你可以相对容易地执行这些操作的程度,你需要考虑以下问题:

  • 是否有共享的状态,你希望所有应用程序都能够随时访问并知道它是完全最新且一致的?

如果是的话,那么你需要执行(1)或者需要一种在整个集群中锁定更改和访问信息的方法,在更改信息的一个地方并确保在允许再次访问它之前复制它。

  • 你能将所有操作转化为一系列事件吗?

假设你希望桌面应用程序调用一个API来向所有其他桌面应用程序发送消息。你可以通过将第一个应用程序发送的消息发送到事件的中央存储库来实现这一点,并让所有应用程序定期与存储库进行检查。消息会在存储库中保留,直到所有其他应用程序都检索到它为止。

或者,假设你可以按任何顺序在信息上执行操作,并且所有获取信息副本的人都可以协调任何事件序列。分布式银行系统中发送资金就是一个很好的例子。

如果所有操作都类似于这些示例,那么你可以通过分布式缓存更简单地实现你的用例,而不是其他用例。但是,这仍然是一个复杂的任务。

另一个考虑因素

在任何分布式系统中,你需要一种方法让集群中的机器找到彼此。它们是否都在同一网络上,并且能够向彼此广播它们的存在?它们是否需要连接到互联网上的中央服务器并通知自己的位置?它们是否有能力在完成这些操作后直接与彼此通信?

英文:

It sounds like you are trying to create a model where multiple copies of the desktop application, with each running on a different computer, share some sort of state or ability to call shared APIs. That's a fairly complex problem, and I don't think you'll find a lot of sample code for doing precisely that. I would suggest googling 'distributed cache', 'distributed transaction', 'message queue', and 'event sourcing'.

If all the applications were running on one computer then you could use memory-mapped files as described in another answer, but it sounds like you need cross-computer access to the information with everyone able to access shared services. This is a non-trivial architecture (particularly without a central server) but there are methods of doing it. The architectures are normally used to coordinate servers.

If you possibly can move the API logic into a web service running once on a single persistent machine, this is going to be a lot easier than anything below.

To manage state between desktop applications running on different machines you need to do one of three things:

  1. Have one desktop app configured to be a central service that maintains the state and serves API requests from the other desktop apps. i.e. something like a web service running on a server, but inside your app. You need a way of getting all the copies of the application to access it. If the applications are going to run on different networks too, then this service needs to be accessible over the Internet. You also have to consider what happens if this machine is not running at the time that another machine needs it.

  2. Cluster of nodes, one of which is elected to be the server at any one time. This solves the issue of a single machine needing to be running at all times, by making all the apps able to be the server and having them decide which one will do this at any particular time. They all then get copies of the state synchronized and can take over if the elected server disappears.

  3. Distributed caching - if all the state changes can be sequenced up locally in the desktop app and then sent out to the others periodically, you can make the cluster operation more performant and resilient by implementing a distributed cache that synchronizes the state between all the apps. You then change things locally to the machine the app is running on and let the distributed cache copy the information to the other apps.

To see how (relatively) easily you can do these things, you want to consider:

  • Is there shared state that you want all the applications to be able to access and know is completely up to date and consistent at all times?

If yes, then you either need to do (1) or need some way to lock changes and access to information throughout the cluster, change the information in one place and ensure it is replicated before you allow access to it again.

  • Can you turn all the operations into a sequence of events?

Let's say you want the desktop apps to call an API that sends all the other desktop apps a message. You can implement this by sending a message from the first app to a central repository of events, and have all the apps check in with the repository every so often. The message is kept in the repository for as long as is needed for all other apps to retrieve it.

Or let's say that you can perform operations in any order on a piece of information and everyone who gets copies of the information can reconcile any sequence of events. A good example is sending money in a distributed banking system.

If all the operations are like those examples, you can implement your use case with distributed caching much more simply than other use cases. It's still tricky to do though.

Another consideration

With any distributed system, you need some way of the machines in the cluster finding each other. Are they all on the same network and can broadcast their presence to each other? Do they need to connect to a central server on the Internet and advise where they can be reached? Do they have the ability to talk directly to each other once they've done that?

huangapple
  • 本文由 发表于 2023年1月8日 22:35:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/75048594.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定