ডাব্লুপিএফ-এ অ্যাপ্লিকেশন.ডাউনভেন্টস () কোথায়?


89

আমার কাছে নিম্নলিখিত নমুনা কোড রয়েছে যা প্রতিবার একটি বোতাম টিপে জুম করে:

এক্সএএমএল:

<Window x:Class="WpfApplication12.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">

    <Canvas x:Name="myCanvas">

        <Canvas.LayoutTransform>
            <ScaleTransform x:Name="myScaleTransform" />
        </Canvas.LayoutTransform> 

        <Button Content="Button" 
                Name="myButton" 
                Canvas.Left="50" 
                Canvas.Top="50" 
                Click="myButton_Click" />
    </Canvas>
</Window>

* .সি

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void myButton_Click(object sender, RoutedEventArgs e)
    {
        Console.WriteLine("scale {0}, location: {1}", 
            myScaleTransform.ScaleX,
            myCanvas.PointToScreen(GetMyByttonLocation()));

        myScaleTransform.ScaleX =
            myScaleTransform.ScaleY =
            myScaleTransform.ScaleX + 1;

        Console.WriteLine("scale {0}, location: {1}",
            myScaleTransform.ScaleX,
            myCanvas.PointToScreen(GetMyByttonLocation()));
    }

    private Point GetMyByttonLocation()
    {
        return new Point(
            Canvas.GetLeft(myButton),
            Canvas.GetTop(myButton));
    }
}

আউটপুটটি হ'ল:

scale 1, location: 296;315
scale 2, location: 296;315

scale 2, location: 346;365
scale 3, location: 346;365

scale 3, location: 396;415
scale 4, location: 396;415

যেমন আপনি দেখতে পাচ্ছেন, একটি সমস্যা আছে, যা আমি ব্যবহার করে সমাধান করার কথা ভেবেছিলাম Application.DoEvents();কিন্তু ... নেট 4 এ এর কোনও পূর্বের উপস্থিতি নেই ।

কি করো?


8
থ্রেডিং? অ্যাপ্লিকেশন.ডাউনভেন্টস () হ'ল দরিদ্র ব্যক্তির যথাযথভাবে বহু-থ্রেডযুক্ত অ্যাপ্লিকেশন লেখার এবং যে কোনও ইভেন্টে চরম দুর্বল অনুশীলন।
কলিন ম্যাকে

4
আমি জানি এটি খারাপ এবং খারাপ, তবে আমি এমন কিছু পছন্দ করি যা কিছুই নয় nothing
serhio

উত্তর:


25

পুরানো অ্যাপ্লিকেশন.ডাউনভেন্টস () পদ্ধতিটি আপনার বর্ণনা অনুসারে প্রসেসিংয়ের জন্য একটি ডিসপ্যাচার বা ব্যাকগ্রাউন্ড ওয়ার্কার থ্রেড ব্যবহার করার পক্ষে ডাব্লুপিএফ-এ অবচিত করা হয়েছে। উভয় অবজেক্টকে কীভাবে ব্যবহার করতে হয় সে সম্পর্কে কয়েকটি নিবন্ধের লিঙ্কগুলি দেখুন।

আপনার যদি অবশ্যই অ্যাপ্লিকেশন.ডাউনভেন্টস () অবশ্যই ব্যবহার করে থাকেন, তবে আপনি কেবল আপনার অ্যাপ্লিকেশনটিতে system.windows.forms.dll আমদানি করতে পারেন এবং পদ্ধতিটি কল করতে পারেন। তবে, এটি সত্যিই প্রস্তাবিত নয়, যেহেতু আপনি ডাব্লুপিএফ সরবরাহ করে এমন সমস্ত সুবিধা হারাচ্ছেন।


4
আমি জানি এটি খারাপ এবং খারাপ, তবে আমি এমন কিছু পছন্দ করি যা কিছুই নয় ... আমি কীভাবে আমার পরিস্থিতিতে ডিসপ্যাচার ব্যবহার করতে পারি?
serhio

4
আমি আপনার অবস্থা বুঝতে পারি। আমি যখন আমার প্রথম ডাব্লুপিএফ অ্যাপ্লিকেশনটি লিখেছিলাম তখন আমি এতে ছিলাম, তবে আমি এগিয়ে গিয়ে নতুন লাইব্রেরিটি শিখতে সময় নিয়েছি এবং এটি দীর্ঘ সময়ের জন্য আরও ভাল ছিল। আমি সময় দেওয়ার জন্য অত্যন্ত পরামর্শ দিই। আপনার বিশেষ ক্ষেত্রে হিসাবে, এটি আমার কাছে এমন মনে হচ্ছে যেন আপনি প্রতিবার ক্লিকের ইভেন্টে আগুনের সময় প্রেরকগুলি স্থানাঙ্কগুলির প্রদর্শন পরিচালনা করতে চান। সঠিক প্রয়োগের জন্য আপনাকে ডিসপ্যাচারে আরও পড়তে হবে।
ডিলি-ও

13
অ্যাপ্লিকেশন
অপসারণ.ডাউনভেন্টস

4
না, এটি একটি ভাল জিনিস ছিল, সেই পদ্ধতিটি ভালটির চেয়ে বেশি ক্ষতি করেছে।
জেসি

4
আমি বিশ্বাস করতে পারি না যে এটি এখনও এই দিন এবং যুগে একটি সমস্যা। আমার মনে আছে অ্যাসিঙ্কের আচরণ অনুকরণের জন্য ভিবি 6-এ ডওভেন্টস কল করা হয়েছিল। সমস্যাটি হ'ল ব্যাকগ্রাউন্ড কর্মী কেবল তখনই কাজ করে যখন আপনি ইউআই প্রসেসিং করছেন না, তবে ইউআই প্রসেসিং - যেমন হাজার হাজার লিস্টবক্স আইটেম তৈরি করা ইউআই থ্রেডটিকে লক করতে পারে। সত্যিই যখন বড় UI কাজ করার দরকার আছে তখন আমাদের কী করা উচিত?
খ্রিস্টান ফান্ডলে

136

এরকম কিছু চেষ্টা করুন

public static void DoEvents()
{
    Application.Current.Dispatcher.Invoke(DispatcherPriority.Background,
                                          new Action(delegate { }));
}

4
এমনকি আমি আবেদনের জন্য একটি এক্সটেনশন পদ্ধতি লিখেছি :)public static void DoEvents(this Application a)
serhio

@ সেরিও: ঝরঝরে এক্সটেনশন পদ্ধতি :)
ফ্রেডরিক হেডব্ল্যাড

4
আমার অবশ্য মন্তব্য করা উচিত যে সত্যিকারের অ্যাপ্লিকেশনটিতে Application.Currentকখনও কখনও নাল থাকে ... সুতরাং এটি সম্ভবত সমতুল্য নয়।
serhio

পারফেক্ট এই উত্তর হওয়া উচিত। Nayayers ক্রেডিট পাওয়া উচিত নয়।
জেসন মারতাজায়া

7
এটি ফ্রেমটিকে ধাক্কা না দেওয়ার কারণে এটি সর্বদা কাজ করবে না, যদি কোনও বাধা নির্দেশনা দেওয়া হয় (যেমন ডাব্লুসিএফ পদ্ধতিতে একটি কল যা এই কমান্ডের সাথে একটি সিনক্রোনিকভাবে চালিয়ে যায়) আপনি সম্ভবত 'রিফ্রেশ' দেখতে পাবেন না কারণ এটি অবরুদ্ধ হয়ে থাকবে .. এজন্য এমএসডিএন রিসোর্স থেকে দেওয়া উত্তর ফ্ল্যাক এইটির চেয়ে আরও সঠিক।
জিওয়াই

58

ঠিক আছে, আমি কেবলমাত্র এমন একটি ক্ষেত্রে আঘাত করেছি যেখানে আমি ডিসপ্যাচার থ্রেডে চালিত কোনও পদ্ধতিতে কাজ শুরু করি এবং এটি ইউআই থ্রেডটি ব্লক না করে ব্লক করা দরকার। দেখা যাচ্ছে যে এমএসডিএন নিজেই ডিসপ্যাচারের উপর ভিত্তি করে একটি ডওভেন্টস () কীভাবে প্রয়োগ করতে হবে তা ব্যাখ্যা করে:

public void DoEvents()
{
    DispatcherFrame frame = new DispatcherFrame();
    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
        new DispatcherOperationCallback(ExitFrame), frame);
    Dispatcher.PushFrame(frame);
}

public object ExitFrame(object f)
{
    ((DispatcherFrame)f).Continue = false;

    return null;
}

( ডিসপ্যাচার থেকে নেওয়া হয়েছে ushপুষ্প ফ্রেম পদ্ধতি )

কেউ কেউ এটিকে একক পদ্ধতিতে পছন্দ করতে পারে যা একই যুক্তি প্রয়োগ করবে:

public static void DoEvents()
{
    var frame = new DispatcherFrame();
    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
        new DispatcherOperationCallback(
            delegate (object f)
            {
                ((DispatcherFrame)f).Continue = false;
                return null;
            }),frame);
    Dispatcher.PushFrame(frame);
}

ভাল লাগছে! এটি মেলিয়াকের প্রস্তাবিত প্রয়োগের চেয়ে নিরাপদ দেখায়। আমি এটি সম্পর্কে একটি ব্লগ পোস্ট
হুগোউরুন

4
@ হুগুরুন যে ব্লগ পোস্টটি জানিয়েছে যে এই পদ্ধতিটি অপ্রয়োজনীয় এবং মেলিয়কের মতো একই বাস্তবায়ন ব্যবহার করা।
লুকাজয়েড

4
@ লুকাজয়েড যতদূর আমি বলতে পারি সহজ প্রয়োগের ফলে হার্ড-টু-ট্রেস লক-আপগুলি হতে পারে। (আমি কারণটির বিষয়ে নিশ্চিত নই, সম্ভবত সমস্যাটি আবারো ডোভেন্টস কলকারী প্রেরণকারী সারিতে কোড, বা প্রেরণকারী কাতারে কোড যা আরও প্রেরণকারী ফ্রেম তৈরি করে। একটি সুপারিশ। (অথবা, অবশ্যই, ডু এভেন্টসটি একেবারেই ব্যবহার করছেন না)
হুগোউরুন

4
অ্যাপ্লিকেশনটি যখন কলব্যাকগুলি বন্ধ করে দিচ্ছে তখন আমাদের উইন্ডোটিতে কোনও সংলাপের পরিবর্তে ভিএমএসকে জড়িত করার উপায়টির সাথে সংলাপের পরিবর্তে ওভারলে দেখানো হচ্ছে এবং আমাদের ব্লক না করে ব্লক করা দরকার। আপনি আমাকে ডওভেন্টস হ্যাক ছাড়াই একটি সমাধান উপস্থাপন করলে আমি আনন্দিত হব।
flq

4
পুরাতন ব্লগ পোস্টে নতুন লিঙ্ক: কেন্ট- বুগার্ট
সিএডি

13

আপনার যদি কেবল উইন্ডো গ্রাফিক আপডেট করতে হয় তবে এর মতো আরও ভাল ব্যবহার করুন

public static void DoEvents()
{
    Application.Current.Dispatcher.Invoke(DispatcherPriority.Render,
                                          new Action(delegate { }));
}

4
DispatcherPriority.Rend ব্যবহার করুন আরও দ্রুত কাজ করে DispatcherPriority.Background। স্টপ ওয়াচারের সাথে আজ পরীক্ষিত
Пекшев

আমি এই কৌশলটি স্রেফ ব্যবহার করেছি তবে ডিসপ্যাচার প্রাইরিটি ব্যবহার করি best সেরা ফলাফলের জন্য পাঠান (সর্বোচ্চ অগ্রাধিকার); আরও প্রতিক্রিয়াশীল UI।
বেন্ট রাসমুসেন

6
myCanvas.UpdateLayout();

পাশাপাশি কাজ বলে মনে হচ্ছে।


এটি আমার কাছে অনেক বেশি নিরাপদ বলে মনে হচ্ছে আমি এটি ব্যবহার করতে যাচ্ছি, তবে আমি অন্যান্য ক্ষেত্রেও ডাউভেন্টস রাখব।
কার্টার মেডলিন

কেন জানি না তবে এটি আমার পক্ষে কাজ করে না। DoEvents () ভাল কাজ করে।
নিউম্যান

আমার ক্ষেত্রে আমাকে এই কাজটিও করতে হয়েছিল ডু ইভেণ্টস ()
জেফ

3

প্রস্তাবিত উভয় পদ্ধতির সাথে একটি সমস্যা হ'ল তারা নিষ্ক্রিয় সিপিইউ ব্যবহার করে (আমার অভিজ্ঞতাতে 12% পর্যন্ত)। উদাহরণস্বরূপ যখন মডেল ইউআই আচরণ এই কৌশলটি ব্যবহার করে প্রয়োগ করা হয় তখন এটি কিছু ক্ষেত্রে এটি সাবঅপটিমাল।

নীচের প্রকরণটি টাইমার ব্যবহার করে ফ্রেমের মধ্যে সর্বনিম্ন বিলম্বের পরিচয় দেয় (নোট করুন এটি রক্সের সাথে এখানে লিখিত হয়েছে তবে যে কোনও নিয়মিত টাইমার দিয়ে অর্জন করা যেতে পারে):

 var minFrameDelay = Observable.Interval(TimeSpan.FromMilliseconds(50)).Take(1).Replay();
 minFrameDelay.Connect();
 // synchronously add a low-priority no-op to the Dispatcher's queue
 Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => minFrameDelay.Wait()));

1

যেহেতু প্রবর্তন asyncএবং awaitএটি এখন (পূর্ববর্তী) * কোডের সিঙ্ক্রোনাস ব্লকের মাধ্যমে ইউআই থ্রেড পার্টওয়ে ত্যাগ করা সম্ভব Task.Delayeg

private async void myButton_Click(object sender, RoutedEventArgs e)
{
    Console.WriteLine("scale {0}, location: {1}", 
        myScaleTransform.ScaleX,
        myCanvas.PointToScreen(GetMyByttonLocation()));

    myScaleTransform.ScaleX =
        myScaleTransform.ScaleY =
        myScaleTransform.ScaleX + 1;

    await Task.Delay(1); // In my experiments, 0 doesn't work. Also, I have noticed
                         // that I need to add as much as 100ms to allow the visual tree
                         // to complete its arrange cycle and for properties to get their
                         // final values (as opposed to NaN for widths etc.)

    Console.WriteLine("scale {0}, location: {1}",
        myScaleTransform.ScaleX,
        myCanvas.PointToScreen(GetMyByttonLocation()));
}

আমি সত্যবাদী হব, আমি উপরের সঠিক কোডটি দিয়ে চেষ্টা করে দেখিনি, তবে আমি যখন ItemsControlব্যয়বহুল আইটেমের টেমপ্লেটযুক্ত অনেকগুলি আইটেম রাখি , তখন কখনও কখনও অন্যটি দিতে সামান্য দেরি যোগ করে আমি টাইট লুপগুলিতে ব্যবহার করি UI আরও সময় স্টাফ।

উদাহরণ স্বরূপ:

        var levelOptions = new ObservableCollection<GameLevelChoiceItem>();

        this.ViewModel[LevelOptionsViewModelKey] = levelOptions;

        var syllabus = await this.LevelRepository.GetSyllabusAsync();
        foreach (var level in syllabus.Levels)
        {
            foreach (var subLevel in level.SubLevels)
            {
                var abilities = new List<GamePlayingAbility>(100);

                foreach (var g in subLevel.Games)
                {
                    var gwa = await this.MetricsRepository.GetGamePlayingAbilityAsync(g.Value);
                    abilities.Add(gwa);
                }

                double PlayingScore = AssessmentMetricsProcessor.ComputePlayingLevelAbility(abilities);

                levelOptions.Add(new GameLevelChoiceItem()
                    {
                        LevelAbilityMetric = PlayingScore,
                        AbilityCaption = PlayingScore.ToString(),
                        LevelCaption = subLevel.Name,
                        LevelDescriptor = level.Ordinal + "." + subLevel.Ordinal,
                        LevelLevels = subLevel.Games.Select(g => g.Value),
                    });

                await Task.Delay(100);
            }
        }

উইন্ডোজ স্টোরগুলিতে, যখন সংগ্রহটিতে একটি দুর্দান্ত থিম স্থানান্তর হয়, তখন প্রভাবটি বেশ আকাঙ্ক্ষিত।

লুক

  • মন্তব্য দেখুন। আমি যখন দ্রুত আমার উত্তরটি লিখছিলাম, তখন আমি কোডের একটি সংকীর্ণ ব্লক নেওয়ার এবং তারপরে থ্রেডটি পুনরায় কলকারীর নিকট ছেড়ে দেওয়ার কাজটি সম্পর্কে ভাবছিলাম, যার ফলস্বরূপ কোডের ব্লকটিকে অ্যাসিঙ্ক্রোনাস করে তোলে। আমি আমার উত্তরটি পুরোপুরি পুনরায় প্রকাশ করতে চাই না কারণ পাঠকরা দেখতে পাচ্ছেন না সার্ভি এবং আমি কী সম্পর্কে ঝগড়া করছিলাম।

"একযোগে ব্লক করে ইউআই থ্রেডটি পার্টওয়ে ছেড়ে দেওয়া এখন সম্ভব" না, তা নয়। আপনি একটি সিঙ্ক্রোনাস পদ্ধতিতে ইউআই থ্রেড থেকে বার্তা পাম্প করার পরিবর্তে সবেমাত্র কোডটিকে অবিচ্ছিন্ন করেছেন । এখন, একটি সঠিকভাবে ডিজাইন করা ডাব্লুপিএফ অ্যাপ্লিকেশনটি হ'ল ইউআই থ্রেডকে দীর্ঘস্থায়ীভাবে ইউআই থ্রেডের মধ্যে প্রথম স্থানে দীর্ঘস্থায়ী ক্রিয়াকলাপগুলি চালিত করে, অ্যাসিঙ্ক্রনি ব্যবহার করে বিদ্যমান বার্তা পাম্পগুলিকে যথাযথভাবে পাম্পগুলি পাম্প করার অনুমতি দেয়।
পরিবেশন করুন

@ সার্ভে কভারগুলির অধীনে, সংকলকটি অপেক্ষিত টাস্কের ধারাবাহিকতা হিসাবে অ্যাসিঙ্কের awaitবাকি পদ্ধতিতে সাইন আপ করতে বাধ্য করবে। সেই ধারাবাহিকতাটি ইউআই থ্রেডে (একই সিঙ্ক প্রসঙ্গে) ঘটবে। তারপরে নিয়ন্ত্রণটি অ্যাসিঙ্ক পদ্ধতির কলারের কাছে ফিরে আসে, যেমন ডাব্লুপিএফস ইভেন্টিং সাবসিস্টেম, যেখানে ইভেন্টগুলি বিলম্বের সময়সীমা শেষ হওয়ার পরে নির্ধারিত ধারাবাহিকতা না চালানো পর্যন্ত চলবে run
লুক পুপলেট

হ্যাঁ, আমি এটি সম্পর্কে ভাল জানি aware এটাই পদ্ধতিটিকে অবিচ্ছিন্ন করে তোলে (কলারের উপর ফলন নিয়ন্ত্রণ এবং কেবল একটি ধারাবাহিকতার সময় নির্ধারণ করে)। আপনার উত্তরে বলা হয়েছে যে পদ্ধতিটি যখন ইউআই আপডেট করার জন্য অ্যাসিনক্রোনি ব্যবহার করে তখন পদ্ধতিটি সিঙ্ক্রোনাস হয় ।
পরিবেশন করুন

প্রথম পদ্ধতি (ওপির কোড) সিঙ্ক্রোনাস, সার্ভি। দ্বিতীয় উদাহরণটি কোনও লুপে থাকা অবস্থায় বা দীর্ঘ তালিকাতে আইটেমগুলি .ালার জন্য ইউআই রাখার জন্য কেবলমাত্র একটি পরামর্শ।
লুক পুপলেট

এবং আপনি যা করেছেন তা সিঙ্ক্রোনাস কোডকে অবিচ্ছিন্ন করে দেওয়া হয়েছে। আপনার বিবরণ যেমনটি বর্ণিত হয়েছে তেমনি আপনি একটি সিঙ্ক্রোনাস পদ্ধতির মধ্যে থেকে ইউআইকে প্রতিক্রিয়াশীল রাখেন নি বা উত্তরটি বলেছে।
পরিবেশন করুন

0

আপনার ডুভেন্ট () ডাব্লুপিএফ-তে করুন:

Thread t = new Thread(() => {
            // do some thing in thread
            
            for (var i = 0; i < 500; i++)
            {
                Thread.Sleep(10); // in thread

                // call owner thread
                this.Dispatcher.Invoke(() => {
                    MediaItem uc = new MediaItem();
                    wpnList.Children.Add(uc);
                });
            }
            

        });
        t.TrySetApartmentState(ApartmentState.STA); //for using Clipboard in Threading
        t.Start();

আমার জন্য ভাল কাজ!


-2

মূল প্রশ্নের উত্তরের: ডু ইভেণ্টস কোথায়?

আমি মনে করি ডু এভেন্টসটি ভিবিএ। এবং ভিবিএতে স্লিপ ফাংশন আছে বলে মনে হয় না। তবে ভিবিএর ঘুম বা বিলম্বের মতো ঠিক একই প্রভাব পাওয়ার একটি উপায় রয়েছে। আমার কাছে মনে হয় যে ডু এভেন্টস ঘুমের সমান (0)।

ভিবি এবং সি # তে আপনি। নেট এ লেনদেন করছেন। এবং মূল প্রশ্নটি একটি সি # প্রশ্ন। সি # তে আপনি থ্রেড.স্লিপ (0) ব্যবহার করবেন যেখানে 0 0 মিলি সেকেন্ড হয়।

তোমার দরকার

using System.Threading.Task;

ব্যবহার করার জন্য ফাইলের শীর্ষে

Sleep(100);

আপনার কোডে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.