在线程之间传递变量

时间:2018-10-24 20:49:08

标签: c# multithreading

我有一个线程处理更新,然后在主Form上调用一个方法以显示结果。

虽然这在某种程度上可行,但同步意味着如果更新进入得太快,则会显示错误的(先前的)数据。

我已经创建了一个对象,该对象使用ref关键字传递,使事物volatile等,但是仍然无法获取同步数据。

public class SharedData
{
    public String notifyTime;
    public String notifyType;
    public String notifyData;
}

public void StartNotificationOutputWorkerThread()
{
        notificationOutputWorker = new NotificationOutputWorker(
                                                    ref oddsUpdates,
                                                    ref willPayUpdates,
                                                    ref eventDataUpdates,
                                                    ref resultDataUpdates,
                                                    ref runnerDataUpdates,
                                                    ref meetingDataUpdates,
                                                    ref optionUpdates,
                                                    ref selectionUpdates,
                                                    ref notifyShare,
                                                    this,
                                                    Context
                                                   );
        notificationOutputWorkerThread = new Thread(notificationOutputWorker.DoWork);
        notificationOutputWorkerThread.Priority = ThreadPriority.AboveNormal;
        notificationOutputWorkerThread.IsBackground = true;
        notificationOutputWorkerThread.Start();
}

public void UpdateNotifications()
{
        Application.DoEvents();
        AddDataItem(LV_GPS, new List<String> 
                              { 
                                notifyShare.notifyTime, 
                                notifyShare.notifyType, 
                                notifyShare.notifyData 
                              });
}

// Worker Thread
public NotificationOutputWorker(
                                 ref UpdateRace aOddsUpdate,
                                 ref UpdateRace aWillPayUpdates,
                                 ref UpdateRace aEventDataUpdates,
                                 ref UpdateRace aResultDataUpdates,
                                 ref UpdateRace aRunnerDataUpdates,
                                 ref UpdateRace aMeetingDataUpdates,
                                 ref UpdateSportsOption aOptionUpdates,
                                 ref UpdateSportsOption aSelectionUpdates,
                                 ref SharedData aNotifyShare,
                                 Form1 _form,
                                 SynchronizationContext _context
                                 )
{
    oddsUpdate         = aOddsUpdate;
    willPayUpdates     = aWillPayUpdates;
    eventDataUpdates   = aEventDataUpdates;
    resultDataUpdates  = aResultDataUpdates;
    runnerDataUpdates = aRunnerDataUpdates;
    meetingDataUpdates = aMeetingDataUpdates;
    optionUpdates      = aOptionUpdates;
    selectionUpdates   = aSelectionUpdates;

    notifyShare = aNotifyShare;

    form = _form;
    this.context = _context;
}

private void UpdateOptions()
{
    while (optionUpdates.syncUpdates.Count > 0)
    {
        try
        {
            String optionNumber = null;
            lock (_locker)
            {
                optionNumber = (String)optionUpdates.syncUpdates.Dequeue();
                optionUpdates.hashes.Remove(optionNumber);
            }
            OutputNotification(GetTime(), "Option", optionNumber);
        }
        catch (Exception ex)
        {

        }
    }
}

public void OutputNotification(String _time, String _type, String _data)
{
    lock (_locker)
    {
        notifyShare.notifyTime = _time;
        notifyShare.notifyType = _type;
        notifyShare.notifyData = _data;
    }

    this.Context.Post(new SendOrPostCallback(notificationUpdate), null);
}

public void notificationUpdate(object state)
{
    form.UpdateNotifications();
    form.DoEvents();
}

2 个答案:

答案 0 :(得分:0)

您没有正确锁定代码;您在更新变量时锁定,然后在开始执行下一个函数时释放它,并且由于变量notifyShare是共享的,因此您的代码不是线程安全的。我建议将您的代码更改为以下内容:

private void UpdateOptions()
{
     while (optionUpdates.syncUpdates.Count > 0)
     {
         try
         {
             String optionNumber = null;
             lock (_locker)
             {
                 optionNumber = (String)optionUpdates.syncUpdates.Dequeue();
                 optionUpdates.hashes.Remove(optionNumber);                 
                 OutputNotification(GetTime(), "Option", optionNumber);
             }          
         }
         catch (Exception ex)  { }
     }
}

public void OutputNotification(String _time, String _type, String _data)
{ 
    notifyShare.notifyTime = _time;
    notifyShare.notifyType = _type;
    notifyShare.notifyData = _data;  
    /* I'm not really sure if this call will be synchronously exected, but if 
     not  then the locking will not be useful and so I prefer to pass the notification 
     details as parameters to the method instead of using a shared object.*/
    this.Context.Post(new SendOrPostCallback(notificationUpdate), null);
}

答案 1 :(得分:0)

public void OutputNotification(String _time, String _type, String _data)
    {
        lock (_locker)
        {
            notifyShare = new SharedData();
            notifyShare.notifyTime = _time;
            notifyShare.notifyType = _type;
            notifyShare.notifyData = _data;
            sharedQueue.Enqueue(notifyShare);
            this.Context.Post(new SendOrPostCallback(notificationUpdate), null);  
        }       
    }

    public void notificationUpdate(object state)
    {
        if (sharedQueue.Count > 0)
        {
            SharedData temp = (SharedData)sharedQueue.Dequeue();
            form.UpdateNotifications(temp);
        }
    }