doghappy / socket.io-client-csharp

socket.io-client implemention for .NET
MIT License
721 stars 124 forks source link

UI thread block incoming `On` events #308

Open AviadCohen24 opened 1 year ago

AviadCohen24 commented 1 year ago

Hey, im developing wpf game that connect to nodejs server via websocket protocol. Now, the events working good until the game start and then the On events not working. For example, if i send event from the server to the client while the ckient on the Home window, the event works without any problem, but if i send the same event while the user on the Game window, the callback event not started. If i set breakpoint on the callback event, the program stops on the breakpoint only when i close the window (press on the X). Help please ! Thanks

doghappy commented 1 year ago

thank for your feedback. do you have a reproducible case/demo?

AviadCohen24 commented 1 year ago

yes, im adding a link to the project rpository on gitlab https://gitlab.com/avi27200p/asteroids The On events declaration is in 'Server' class. The On callbacks not working only when GameView is show.

doghappy commented 1 year ago

could not connect to server 127.0.0.1:3001, no socket.io server in project

AviadCohen24 commented 1 year ago

sorry mu mistake, i fotgot to add the server side. the next link is the repo for the server side https://gitlab.com/avi27200p/asteroid-game-server Thanks for your respone !

doghappy commented 1 year ago

You gave me a complicated program. After I read the code, I created the database and tables. After successfully registering a user, I still can't start the game for some reason.

so I tried to create a simple demo, but I can receive messages

server:

const http = require('http');
const express = require('express')
const app = express()
const bodyParser = require('body-parser');
app.use(bodyParser.json());
const server = http.createServer(app);
const socketio = require('socket.io');
const io = socketio(server);

io.on('connection', (socket) =>{
    socket.broadcast.emit('public', `${socket.id} joined the channel`);
    socket.on('msg', (msg) => {
        socket.broadcast.emit('msg', `${socket.id}: ${msg}`);
    });
});

io.listen(3001);

MainWindow.xaml:

<Window x:Class="WpfApplication1.MainWindow"
        ...
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <ListView ItemsSource="{Binding Messages}"></ListView>
        <Button Grid.Row="1" Content="Dialog" Click="Dialog_OnClick" />
    </Grid>
</Window>

MainWindow.cs:

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        Messages = new ObservableCollection<string>();
        DataContext = this;
    }

    public SocketIO _io;
    public ObservableCollection<string> Messages { get; }

    private async void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
    {
        _io = new SocketIO("http://localhost:3001");
        _io.On("msg", res =>
        {
            Dispatcher.Invoke(() => Messages.Add(res.GetValue<string>()));
        });
        await _io.ConnectAsync();
    }

    private void Dialog_OnClick(object sender, RoutedEventArgs e)
    {
        var dialog = new MyDialog(_io);
        dialog.ShowDialog();
    }
}

MyDialog.xmal:

<Window x:Class="WpfApplication1.MyDialog"
        ...
        Title="MyDialog" Height="450" Width="800">
    <StackPanel>
        <TextBox Text="{Binding Message, Mode=TwoWay}"/>
        <Button Content="Send" Click="Send_OnClick" />
    </StackPanel>
</Window>

MyDialog.cs:

public partial class MyDialog : Window, INotifyPropertyChanged
{
    public MyDialog(SocketIO socketIo)
    {
        InitializeComponent();
        DataContext = this;
        _socketIo = socketIo;
    }

    private readonly SocketIO _socketIo;

    private string _message;

    public string Message
    {
        get => _message;
        set => SetField(ref _message, value);
    }

    private async void Send_OnClick(object sender, RoutedEventArgs e)
    {
        await _socketIo.EmitAsync("msg", Message);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

Main window is a public channel, everyone can see messages sent by other users.

image

Dose this can emulate your game?

AviadCohen24 commented 1 year ago

Unfortunately I don't think that your code can emulate my game, because my problem is caused by high activity of the ui thread, and your code don't have this activity on the ui thread.